Changeset 105745 in webkit


Ignore:
Timestamp:
Jan 24, 2012 10:02:08 AM (12 years ago)
Author:
mario@webkit.org
Message:

Web Inspector: CodeGeneratorInspector.py: put TypeBuilder namespace in a separate sources
https://bugs.webkit.org/show_bug.cgi?id=76868

Patch by Peter Rybin <peter.rybin@gmail.com> on 2012-01-24
Reviewed by Yury Semikhatsky.

Configurations of (hopefully) all build systems are fixed.

  • CMakeLists.txt:
  • DerivedSources.make:
  • DerivedSources.pri:
  • GNUmakefile.am:
  • GNUmakefile.list.am:
  • WebCore.gyp/WebCore.gyp:
  • WebCore.gypi:
  • WebCore.vcproj/WebCore.vcproj:
  • WebCore.xcodeproj/project.pbxproj:
  • inspector/CodeGeneratorInspector.py:

(dash_to_camelcase):
(InspectorFrontend_h):
(InspectorBackendDispatcher_h):

Location:
trunk/Source/WebCore
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r105743 r105745  
    2121        (InspectorFrontend_h):
    2222        (InspectorBackendDispatcher_h):
     23
     242012-01-24  Mario Sanchez Prada  <msanchez@igalia.com>
     25
     26        [GTK] Refactor GTK's accessibilitity code to be more modular
     27        https://bugs.webkit.org/show_bug.cgi?id=76783
     28
     29        Reviewed by Martin Robinson.
     30
     31        New files for the implementation of the AtkText interface,
     32        containing the related code from WebKitAccessibleWrapperAtk.cpp.
     33
     34        * accessibility/gtk/WebKitAccessibleInterfaceText.cpp: Added.
     35        (core):
     36        (textForRenderer):
     37        (textForObject):
     38        (getGailTextUtilForAtk):
     39        (getPangoLayoutForAtk):
     40        (baselinePositionForRenderObject):
     41        (getAttributeSetForAccessibilityObject):
     42        (compareAttribute):
     43        (attributeSetDifference):
     44        (accessibilityObjectLength):
     45        (getAccessibilityObjectForOffset):
     46        (getRunAttributesFromAccesibilityObject):
     47        (textExtents):
     48        (getSelectionOffsetsForObject):
     49        (webkitAccessibleTextInterfaceInit):
     50        (webkitAccessibleTextGetText):
     51        (webkitAccessibleTextGetTextAfterOffset):
     52        (webkitAccessibleTextGetTextAtOffset):
     53        (webkitAccessibleTextGetTextBeforeOffset):
     54        (webkitAccessibleTextGetCharacterAtOffset):
     55        (webkitAccessibleTextGetCaretOffset):
     56        (webkitAccessibleTextGetRunAttributes):
     57        (webkitAccessibleTextGetDefaultAttributes):
     58        (webkitAccessibleTextGetCharacterExtents):
     59        (webkitAccessibleTextGetRangeExtents):
     60        (webkitAccessibleTextGetCharacterCount):
     61        (webkitAccessibleTextGetOffsetAtPoint):
     62        (webkitAccessibleTextGetNSelections):
     63        (webkitAccessibleTextGetSelection):
     64        (webkitAccessibleTextAddSelection):
     65        (webkitAccessibleTextRemoveSelection):
     66        (webkitAccessibleTextSetSelection):
     67        (webkitAccessibleTextSetCaretOffset):
     68        * accessibility/gtk/WebKitAccessibleInterfaceText.h: Added.
     69
     70        Move common function selectionBelongsToObject out from the wrapper
     71        to the utility file, used from WebKitAccessibleInterfaceText.cpp.
     72
     73        * accessibility/gtk/WebKitAccessibleUtil.cpp:
     74        (selectionBelongsToObject): Taken from WebKitAccessibleWrapperAtk.cpp.
     75        * accessibility/gtk/WebKitAccessibleUtil.h:
     76        * accessibility/gtk/WebKitAccessibleWrapperAtk.cpp: Remove local
     77        implementation of selectionBelongsToObject, and the code related
     78        to the implementation of the AtkText interface.
     79        (webkit_accessible_get_name): Update call to the former function
     80        webkit_accessible_text_get_text and use the new function name.
     81        (webkit_accessible_table_get_column_description): Ditto.
     82        (webkit_accessible_table_get_row_description): Ditto.
     83
     84        Add new files to build files.
     85
     86        * GNUmakefile.list.am: Add WebKitAccessibleInterfaceText.[h|cpp].
     87        * WebCore.gypi: Ditto.
    2388
    24892012-01-24  Mario Sanchez Prada  <msanchez@igalia.com>
  • trunk/Source/WebCore/GNUmakefile.list.am

    r105743 r105745  
    44404440        Source/WebCore/accessibility/gtk/WebKitAccessibleInterfaceSelection.cpp \
    44414441        Source/WebCore/accessibility/gtk/WebKitAccessibleInterfaceSelection.h \
     4442        Source/WebCore/accessibility/gtk/WebKitAccessibleInterfaceText.cpp \
     4443        Source/WebCore/accessibility/gtk/WebKitAccessibleInterfaceText.h \
    44424444        Source/WebCore/accessibility/gtk/WebKitAccessibleInterfaceValue.cpp \
    44434445        Source/WebCore/accessibility/gtk/WebKitAccessibleInterfaceValue.h \
  • trunk/Source/WebCore/WebCore.gypi

    r105743 r105745  
    13621362            'accessibility/gtk/WebKitAccessibleInterfaceSelection.cpp',
    13631363            'accessibility/gtk/WebKitAccessibleInterfaceSelection.h',
     1364            'accessibility/gtk/WebKitAccessibleInterfaceText.cpp',
     1365            'accessibility/gtk/WebKitAccessibleInterfaceText.h',
    13641366            'accessibility/gtk/WebKitAccessibleInterfaceValue.cpp',
    13651367            'accessibility/gtk/WebKitAccessibleInterfaceValue.h',
  • trunk/Source/WebCore/accessibility/gtk/WebKitAccessibleUtil.cpp

    r105721 r105745  
    3535#include "FrameView.h"
    3636#include "IntRect.h"
     37#include "Node.h"
     38#include "Range.h"
     39#include "VisibleSelection.h"
    3740
    3841#include <wtf/text/AtomicString.h>
     
    8285    return returnedString.data();
    8386}
     87
     88bool selectionBelongsToObject(AccessibilityObject* coreObject, VisibleSelection& selection)
     89{
     90    if (!coreObject || !coreObject->isAccessibilityRenderObject())
     91        return false;
     92
     93    if (selection.isNone())
     94        return false;
     95
     96    RefPtr<Range> range = selection.toNormalizedRange();
     97    if (!range)
     98        return false;
     99
     100    // We want to check that both the selection intersects the node
     101    // AND that the selection is not just "touching" one of the
     102    // boundaries for the selected node. We want to check whether the
     103    // node is actually inside the region, at least partially.
     104    Node* node = coreObject->node();
     105    Node* lastDescendant = node->lastDescendant();
     106    ExceptionCode ec = 0;
     107    return (range->intersectsNode(node, ec)
     108            && (range->endContainer() != node || range->endOffset())
     109            && (range->startContainer() != lastDescendant || range->startOffset() != lastOffsetInNode(lastDescendant)));
     110}
  • trunk/Source/WebCore/accessibility/gtk/WebKitAccessibleUtil.h

    r105721 r105745  
    2929class AccessibilityObject;
    3030class IntRect;
     31class VisibleSelection;
    3132}
    3233
     
    3738const char* returnString(const String&);
    3839
     40bool selectionBelongsToObject(WebCore::AccessibilityObject*, WebCore::VisibleSelection&);
     41
    3942#endif // WebKitAccessibleUtil_h
  • trunk/Source/WebCore/accessibility/gtk/WebKitAccessibleWrapperAtk.cpp

    r105740 r105745  
    7272#include "WebKitAccessibleInterfaceImage.h"
    7373#include "WebKitAccessibleInterfaceSelection.h"
     74#include "WebKitAccessibleInterfaceText.h"
    7475#include "WebKitAccessibleInterfaceValue.h"
    7576#include "WebKitAccessibleUtil.h"
     
    117118}
    118119
    119 static AccessibilityObject* core(AtkText* text)
    120 {
    121     return core(ATK_OBJECT(text));
    122 }
    123 
    124120static AccessibilityObject* core(AtkTable* table)
    125121{
    126122    return core(ATK_OBJECT(table));
    127123}
    128 
    129 static gchar* webkit_accessible_text_get_text(AtkText*, gint startOffset, gint endOffset);
    130124
    131125static const gchar* webkit_accessible_get_name(AtkObject* object)
     
    140134            AtkObject* atkObject = label->wrapper();
    141135            if (ATK_IS_TEXT(atkObject))
    142                 return webkit_accessible_text_get_text(ATK_TEXT(atkObject), 0, -1);
     136                return webkitAccessibleTextGetText(ATK_TEXT(atkObject), 0, -1);
    143137        }
    144138
     
    584578}
    585579
    586 static bool selectionBelongsToObject(AccessibilityObject* coreObject, VisibleSelection& selection)
    587 {
    588     if (!coreObject || !coreObject->isAccessibilityRenderObject())
    589         return false;
    590 
    591     if (selection.isNone())
    592         return false;
    593 
    594     RefPtr<Range> range = selection.toNormalizedRange();
    595     if (!range)
    596         return false;
    597 
    598     // We want to check that both the selection intersects the node
    599     // AND that the selection is not just "touching" one of the
    600     // boundaries for the selected node. We want to check whether the
    601     // node is actually inside the region, at least partially.
    602     Node* node = coreObject->node();
    603     Node* lastDescendant = node->lastDescendant();
    604     ExceptionCode ec = 0;
    605     return (range->intersectsNode(node, ec)
    606             && (range->endContainer() != node || range->endOffset())
    607             && (range->startContainer() != lastDescendant || range->startOffset() != lastOffsetInNode(lastDescendant)));
    608 }
    609 
    610580static bool isTextWithCaret(AccessibilityObject* coreObject)
    611581{
     
    824794}
    825795
    826 // Text
    827 
    828 static gchar* utf8Substr(const gchar* string, gint start, gint end)
    829 {
    830     ASSERT(string);
    831     glong strLen = g_utf8_strlen(string, -1);
    832     if (start > strLen || end > strLen)
    833         return 0;
    834     gchar* startPtr = g_utf8_offset_to_pointer(string, start);
    835     gsize lenInBytes = g_utf8_offset_to_pointer(string, end + 1) -  startPtr;
    836     gchar* output = static_cast<gchar*>(g_malloc0(lenInBytes + 1));
    837     return g_utf8_strncpy(output, startPtr, end - start + 1);
    838 }
    839 
    840 // This function is not completely general, is it's tied to the
    841 // internals of WebCore's text presentation.
    842 static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int from, int to)
    843 {
    844     CString stringUTF8 = UTF8Encoding().encode(characters, length, QuestionMarksForUnencodables);
    845     gchar* utf8String = utf8Substr(stringUTF8.data(), from, to);
    846     if (!g_utf8_validate(utf8String, -1, 0)) {
    847         g_free(utf8String);
    848         return 0;
    849     }
    850     gsize len = strlen(utf8String);
    851     GString* ret = g_string_new_len(0, len);
    852     gchar* ptr = utf8String;
    853 
    854     // WebCore introduces line breaks in the text that do not reflect
    855     // the layout you see on the screen, replace them with spaces
    856     while (len > 0) {
    857         gint index, start;
    858         pango_find_paragraph_boundary(ptr, len, &index, &start);
    859         g_string_append_len(ret, ptr, index);
    860         if (index == start)
    861             break;
    862         g_string_append_c(ret, ' ');
    863         ptr += start;
    864         len -= start;
    865     }
    866 
    867     g_free(utf8String);
    868     return g_string_free(ret, FALSE);
    869 }
    870 
    871 gchar* textForRenderer(RenderObject* renderer)
    872 {
    873     GString* resultText = g_string_new(0);
    874 
    875     if (!renderer)
    876         return g_string_free(resultText, FALSE);
    877 
    878     // For RenderBlocks, piece together the text from the RenderText objects they contain.
    879     for (RenderObject* object = renderer->firstChild(); object; object = object->nextSibling()) {
    880         if (object->isBR()) {
    881             g_string_append(resultText, "\n");
    882             continue;
    883         }
    884 
    885         RenderText* renderText;
    886         if (object->isText())
    887             renderText = toRenderText(object);
    888         else {
    889             if (object->isReplaced())
    890                 g_string_append_unichar(resultText, objectReplacementCharacter);
    891 
    892             // We need to check children, if any, to consider when
    893             // current object is not a text object but some of its
    894             // children are, in order not to miss those portions of
    895             // text by not properly handling those situations
    896             if (object->firstChild())
    897                 g_string_append(resultText, textForRenderer(object));
    898 
    899             continue;
    900         }
    901 
    902         InlineTextBox* box = renderText ? renderText->firstTextBox() : 0;
    903         while (box) {
    904             gchar* text = convertUniCharToUTF8(renderText->characters(), renderText->textLength(), box->start(), box->end());
    905             g_string_append(resultText, text);
    906             // Newline chars in the source result in separate text boxes, so check
    907             // before adding a newline in the layout. See bug 25415 comment #78.
    908             // If the next sibling is a BR, we'll add the newline when we examine that child.
    909             if (!box->nextOnLineExists() && (!object->nextSibling() || !object->nextSibling()->isBR()))
    910                 g_string_append(resultText, "\n");
    911             box = box->nextTextBox();
    912         }
    913     }
    914 
    915     // Insert the text of the marker for list item in the right place, if present
    916     if (renderer->isListItem()) {
    917         String markerText = toRenderListItem(renderer)->markerTextWithSuffix();
    918         if (renderer->style()->direction() == LTR)
    919             g_string_prepend(resultText, markerText.utf8().data());
    920         else
    921             g_string_append(resultText, markerText.utf8().data());
    922     }
    923 
    924     return g_string_free(resultText, FALSE);
    925 }
    926 
    927 gchar* textForObject(AccessibilityObject* coreObject)
    928 {
    929     GString* str = g_string_new(0);
    930 
    931     // For text controls, we can get the text line by line.
    932     if (coreObject->isTextControl()) {
    933         unsigned textLength = coreObject->textLength();
    934         int lineNumber = 0;
    935         PlainTextRange range = coreObject->doAXRangeForLine(lineNumber);
    936         while (range.length) {
    937             // When a line of text wraps in a text area, the final space is removed.
    938             if (range.start + range.length < textLength)
    939                 range.length -= 1;
    940             String lineText = coreObject->doAXStringForRange(range);
    941             g_string_append(str, lineText.utf8().data());
    942             g_string_append(str, "\n");
    943             range = coreObject->doAXRangeForLine(++lineNumber);
    944         }
    945     } else if (coreObject->isAccessibilityRenderObject()) {
    946         GOwnPtr<gchar> rendererText(textForRenderer(coreObject->renderer()));
    947         g_string_append(str, rendererText.get());
    948     }
    949 
    950     return g_string_free(str, FALSE);
    951 }
    952 
    953 static gchar* webkit_accessible_text_get_text(AtkText* text, gint startOffset, gint endOffset)
    954 {
    955     AccessibilityObject* coreObject = core(text);
    956 
    957     int end = endOffset;
    958     if (endOffset == -1) {
    959         end = coreObject->stringValue().length();
    960         if (!end)
    961             end = coreObject->textUnderElement().length();
    962     }
    963 
    964     String ret;
    965     if (coreObject->isTextControl())
    966         ret = coreObject->doAXStringForRange(PlainTextRange(0, endOffset));
    967     else {
    968         ret = coreObject->stringValue();
    969         if (!ret)
    970             ret = coreObject->textUnderElement();
    971     }
    972 
    973     if (!ret.length()) {
    974         // This can happen at least with anonymous RenderBlocks (e.g. body text amongst paragraphs)
    975         ret = String(textForObject(coreObject));
    976         if (!end)
    977             end = ret.length();
    978     }
    979 
    980     // Prefix a item number/bullet if needed
    981     if (coreObject->roleValue() == ListItemRole) {
    982         RenderObject* objRenderer = coreObject->renderer();
    983         if (objRenderer && objRenderer->isListItem()) {
    984             String markerText = toRenderListItem(objRenderer)->markerTextWithSuffix();
    985             ret = objRenderer->style()->direction() == LTR ? markerText + ret : ret + markerText;
    986             if (endOffset == -1)
    987                 end += markerText.length();
    988         }
    989     }
    990 
    991     ret = ret.substring(startOffset, end - startOffset);
    992     return g_strdup(ret.utf8().data());
    993 }
    994 
    995 static GailTextUtil* getGailTextUtilForAtk(AtkText* textObject)
    996 {
    997     GailTextUtil* gailTextUtil = gail_text_util_new();
    998     gail_text_util_text_setup(gailTextUtil, webkit_accessible_text_get_text(textObject, 0, -1));
    999     return gailTextUtil;
    1000 }
    1001 
    1002 static PangoLayout* getPangoLayoutForAtk(AtkText* textObject)
    1003 {
    1004     AccessibilityObject* coreObject = core(textObject);
    1005 
    1006     Document* document = coreObject->document();
    1007     if (!document)
    1008         return 0;
    1009 
    1010     HostWindow* hostWindow = document->view()->hostWindow();
    1011     if (!hostWindow)
    1012         return 0;
    1013     PlatformPageClient webView = hostWindow->platformPageClient();
    1014     if (!webView)
    1015         return 0;
    1016 
    1017     // Create a string with the layout as it appears on the screen
    1018     PangoLayout* layout = gtk_widget_create_pango_layout(static_cast<GtkWidget*>(webView), textForObject(coreObject));
    1019     return layout;
    1020 }
    1021 
    1022 static gchar* webkit_accessible_text_get_text_after_offset(AtkText* text, gint offset, AtkTextBoundary boundaryType, gint* startOffset, gint* endOffset)
    1023 {
    1024     return gail_text_util_get_text(getGailTextUtilForAtk(text), getPangoLayoutForAtk(text), GAIL_AFTER_OFFSET, boundaryType, offset, startOffset, endOffset);
    1025 }
    1026 
    1027 static gchar* webkit_accessible_text_get_text_at_offset(AtkText* text, gint offset, AtkTextBoundary boundaryType, gint* startOffset, gint* endOffset)
    1028 {
    1029     return gail_text_util_get_text(getGailTextUtilForAtk(text), getPangoLayoutForAtk(text), GAIL_AT_OFFSET, boundaryType, offset, startOffset, endOffset);
    1030 }
    1031 
    1032 static gchar* webkit_accessible_text_get_text_before_offset(AtkText* text, gint offset, AtkTextBoundary boundaryType, gint* startOffset, gint* endOffset)
    1033 {
    1034     return gail_text_util_get_text(getGailTextUtilForAtk(text), getPangoLayoutForAtk(text), GAIL_BEFORE_OFFSET, boundaryType, offset, startOffset, endOffset);
    1035 }
    1036 
    1037 static gunichar webkit_accessible_text_get_character_at_offset(AtkText* text, gint offset)
    1038 {
    1039     notImplemented();
    1040     return 0;
    1041 }
    1042 
    1043 static gint webkit_accessible_text_get_caret_offset(AtkText* text)
    1044 {
    1045     // coreObject is the unignored object whose offset the caller is requesting.
    1046     // focusedObject is the object with the caret. It is likely ignored -- unless it's a link.
    1047     AccessibilityObject* coreObject = core(text);
    1048     if (!coreObject->isAccessibilityRenderObject())
    1049         return 0;
    1050 
    1051     // We need to make sure we pass a valid object as reference.
    1052     if (coreObject->accessibilityIsIgnored())
    1053         coreObject = coreObject->parentObjectUnignored();
    1054     if (!coreObject)
    1055         return 0;
    1056 
    1057     int offset;
    1058     if (!objectFocusedAndCaretOffsetUnignored(coreObject, offset))
    1059         return 0;
    1060 
    1061     RenderObject* renderer = coreObject->renderer();
    1062     if (renderer && renderer->isListItem()) {
    1063         String markerText = toRenderListItem(renderer)->markerTextWithSuffix();
    1064 
    1065         // We need to adjust the offset for the list item marker.
    1066         offset += markerText.length();
    1067     }
    1068 
    1069     // TODO: Verify this for RTL text.
    1070     return offset;
    1071 }
    1072 
    1073 static int baselinePositionForRenderObject(RenderObject* renderObject)
    1074 {
    1075     // FIXME: This implementation of baselinePosition originates from RenderObject.cpp and was
    1076     // removed in r70072. The implementation looks incorrect though, because this is not the
    1077     // baseline of the underlying RenderObject, but of the AccessibilityRenderObject.
    1078     const FontMetrics& fontMetrics = renderObject->firstLineStyle()->fontMetrics();
    1079     return fontMetrics.ascent() + (renderObject->firstLineStyle()->computedLineHeight() - fontMetrics.height()) / 2;
    1080 }
    1081 
    1082 static AtkAttributeSet* getAttributeSetForAccessibilityObject(const AccessibilityObject* object)
    1083 {
    1084     if (!object->isAccessibilityRenderObject())
    1085         return 0;
    1086 
    1087     RenderObject* renderer = object->renderer();
    1088     RenderStyle* style = renderer->style();
    1089 
    1090     AtkAttributeSet* result = 0;
    1091     GOwnPtr<gchar> buffer(g_strdup_printf("%i", style->fontSize()));
    1092     result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_SIZE), buffer.get());
    1093 
    1094     Color bgColor = style->visitedDependentColor(CSSPropertyBackgroundColor);
    1095     if (bgColor.isValid()) {
    1096         buffer.set(g_strdup_printf("%i,%i,%i",
    1097                                    bgColor.red(), bgColor.green(), bgColor.blue()));
    1098         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_BG_COLOR), buffer.get());
    1099     }
    1100 
    1101     Color fgColor = style->visitedDependentColor(CSSPropertyColor);
    1102     if (fgColor.isValid()) {
    1103         buffer.set(g_strdup_printf("%i,%i,%i",
    1104                                    fgColor.red(), fgColor.green(), fgColor.blue()));
    1105         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_FG_COLOR), buffer.get());
    1106     }
    1107 
    1108     int baselinePosition;
    1109     bool includeRise = true;
    1110     switch (style->verticalAlign()) {
    1111     case SUB:
    1112         baselinePosition = -1 * baselinePositionForRenderObject(renderer);
    1113         break;
    1114     case SUPER:
    1115         baselinePosition = baselinePositionForRenderObject(renderer);
    1116         break;
    1117     case BASELINE:
    1118         baselinePosition = 0;
    1119         break;
    1120     default:
    1121         includeRise = false;
    1122         break;
    1123     }
    1124 
    1125     if (includeRise) {
    1126         buffer.set(g_strdup_printf("%i", baselinePosition));
    1127         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_RISE), buffer.get());
    1128     }
    1129 
    1130     if (!style->textIndent().isUndefined()) {
    1131         int indentation = style->textIndent().calcValue(object->size().width());
    1132         buffer.set(g_strdup_printf("%i", indentation));
    1133         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_INDENT), buffer.get());
    1134     }
    1135 
    1136     String fontFamilyName = style->font().family().family().string();
    1137     if (fontFamilyName.left(8) == "-webkit-")
    1138         fontFamilyName = fontFamilyName.substring(8);
    1139 
    1140     result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_FAMILY_NAME), fontFamilyName.utf8().data());
    1141 
    1142     int fontWeight = -1;
    1143     switch (style->font().weight()) {
    1144     case FontWeight100:
    1145         fontWeight = 100;
    1146         break;
    1147     case FontWeight200:
    1148         fontWeight = 200;
    1149         break;
    1150     case FontWeight300:
    1151         fontWeight = 300;
    1152         break;
    1153     case FontWeight400:
    1154         fontWeight = 400;
    1155         break;
    1156     case FontWeight500:
    1157         fontWeight = 500;
    1158         break;
    1159     case FontWeight600:
    1160         fontWeight = 600;
    1161         break;
    1162     case FontWeight700:
    1163         fontWeight = 700;
    1164         break;
    1165     case FontWeight800:
    1166         fontWeight = 800;
    1167         break;
    1168     case FontWeight900:
    1169         fontWeight = 900;
    1170     }
    1171     if (fontWeight > 0) {
    1172         buffer.set(g_strdup_printf("%i", fontWeight));
    1173         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_WEIGHT), buffer.get());
    1174     }
    1175 
    1176     switch (style->textAlign()) {
    1177     case TAAUTO:
    1178     case TASTART:
    1179     case TAEND:
    1180         break;
    1181     case LEFT:
    1182     case WEBKIT_LEFT:
    1183         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_JUSTIFICATION), "left");
    1184         break;
    1185     case RIGHT:
    1186     case WEBKIT_RIGHT:
    1187         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_JUSTIFICATION), "right");
    1188         break;
    1189     case CENTER:
    1190     case WEBKIT_CENTER:
    1191         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_JUSTIFICATION), "center");
    1192         break;
    1193     case JUSTIFY:
    1194         result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_JUSTIFICATION), "fill");
    1195     }
    1196 
    1197     result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_UNDERLINE), (style->textDecoration() & UNDERLINE) ? "single" : "none");
    1198 
    1199     result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_STYLE), style->font().italic() ? "italic" : "normal");
    1200 
    1201     result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_STRIKETHROUGH), (style->textDecoration() & LINE_THROUGH) ? "true" : "false");
    1202 
    1203     result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_INVISIBLE), (style->visibility() == HIDDEN) ? "true" : "false");
    1204 
    1205     result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_EDITABLE), object->isReadOnly() ? "false" : "true");
    1206 
    1207     return result;
    1208 }
    1209 
    1210 static gint compareAttribute(const AtkAttribute* a, const AtkAttribute* b)
    1211 {
    1212     return g_strcmp0(a->name, b->name) || g_strcmp0(a->value, b->value);
    1213 }
    1214 
    1215 // Returns an AtkAttributeSet with the elements of a1 which are either
    1216 // not present or different in a2. Neither a1 nor a2 should be used
    1217 // after calling this function.
    1218 static AtkAttributeSet* attributeSetDifference(AtkAttributeSet* a1, AtkAttributeSet* a2)
    1219 {
    1220     if (!a2)
    1221         return a1;
    1222 
    1223     AtkAttributeSet* i = a1;
    1224     AtkAttributeSet* found;
    1225     AtkAttributeSet* toDelete = 0;
    1226 
    1227     while (i) {
    1228         found = g_slist_find_custom(a2, i->data, (GCompareFunc)compareAttribute);
    1229         if (found) {
    1230             AtkAttributeSet* t = i->next;
    1231             toDelete = g_slist_prepend(toDelete, i->data);
    1232             a1 = g_slist_delete_link(a1, i);
    1233             i = t;
    1234         } else
    1235             i = i->next;
    1236     }
    1237 
    1238     atk_attribute_set_free(a2);
    1239     atk_attribute_set_free(toDelete);
    1240     return a1;
    1241 }
    1242 
    1243 static guint accessibilityObjectLength(const AccessibilityObject* object)
    1244 {
    1245     // Non render objects are not taken into account
    1246     if (!object->isAccessibilityRenderObject())
    1247         return 0;
    1248 
    1249     // For those objects implementing the AtkText interface we use the
    1250     // well known API to always get the text in a consistent way
    1251     AtkObject* atkObj = ATK_OBJECT(object->wrapper());
    1252     if (ATK_IS_TEXT(atkObj)) {
    1253         GOwnPtr<gchar> text(webkit_accessible_text_get_text(ATK_TEXT(atkObj), 0, -1));
    1254         return g_utf8_strlen(text.get(), -1);
    1255     }
    1256 
    1257     // Even if we don't expose list markers to Assistive
    1258     // Technologies, we need to have a way to measure their length
    1259     // for those cases when it's needed to take it into account
    1260     // separately (as in getAccessibilityObjectForOffset)
    1261     RenderObject* renderer = object->renderer();
    1262     if (renderer && renderer->isListMarker()) {
    1263         RenderListMarker* marker = toRenderListMarker(renderer);
    1264         return marker->text().length() + marker->suffix().length();
    1265     }
    1266 
    1267     return 0;
    1268 }
    1269 
    1270 static const AccessibilityObject* getAccessibilityObjectForOffset(const AccessibilityObject* object, guint offset, gint* startOffset, gint* endOffset)
    1271 {
    1272     const AccessibilityObject* result;
    1273     guint length = accessibilityObjectLength(object);
    1274     if (length > offset) {
    1275         *startOffset = 0;
    1276         *endOffset = length;
    1277         result = object;
    1278     } else {
    1279         *startOffset = -1;
    1280         *endOffset = -1;
    1281         result = 0;
    1282     }
    1283 
    1284     if (!object->firstChild())
    1285         return result;
    1286 
    1287     AccessibilityObject* child = object->firstChild();
    1288     guint currentOffset = 0;
    1289     guint childPosition = 0;
    1290     while (child && currentOffset <= offset) {
    1291         guint childLength = accessibilityObjectLength(child);
    1292         currentOffset = childLength + childPosition;
    1293         if (currentOffset > offset) {
    1294             gint childStartOffset;
    1295             gint childEndOffset;
    1296             const AccessibilityObject* grandChild = getAccessibilityObjectForOffset(child, offset-childPosition,  &childStartOffset, &childEndOffset);
    1297             if (childStartOffset >= 0) {
    1298                 *startOffset = childStartOffset + childPosition;
    1299                 *endOffset = childEndOffset + childPosition;
    1300                 result = grandChild;
    1301             }
    1302         } else {
    1303             childPosition += childLength;
    1304             child = child->nextSibling();
    1305         }
    1306     }
    1307     return result;
    1308 }
    1309 
    1310 static AtkAttributeSet* getRunAttributesFromAccesibilityObject(const AccessibilityObject* element, gint offset, gint* startOffset, gint* endOffset)
    1311 {
    1312     const AccessibilityObject *child = getAccessibilityObjectForOffset(element, offset, startOffset, endOffset);
    1313     if (!child) {
    1314         *startOffset = -1;
    1315         *endOffset = -1;
    1316         return 0;
    1317     }
    1318 
    1319     AtkAttributeSet* defaultAttributes = getAttributeSetForAccessibilityObject(element);
    1320     AtkAttributeSet* childAttributes = getAttributeSetForAccessibilityObject(child);
    1321 
    1322     return attributeSetDifference(childAttributes, defaultAttributes);
    1323 }
    1324 
    1325 static AtkAttributeSet* webkit_accessible_text_get_run_attributes(AtkText* text, gint offset, gint* startOffset, gint* endOffset)
    1326 {
    1327     AccessibilityObject* coreObject = core(text);
    1328     AtkAttributeSet* result;
    1329 
    1330     if (!coreObject) {
    1331         *startOffset = 0;
    1332         *endOffset = atk_text_get_character_count(text);
    1333         return 0;
    1334     }
    1335 
    1336     if (offset == -1)
    1337         offset = atk_text_get_caret_offset(text);
    1338 
    1339     result = getRunAttributesFromAccesibilityObject(coreObject, offset, startOffset, endOffset);
    1340 
    1341     if (*startOffset < 0) {
    1342         *startOffset = offset;
    1343         *endOffset = offset;
    1344     }
    1345 
    1346     return result;
    1347 }
    1348 
    1349 static AtkAttributeSet* webkit_accessible_text_get_default_attributes(AtkText* text)
    1350 {
    1351     AccessibilityObject* coreObject = core(text);
    1352     if (!coreObject || !coreObject->isAccessibilityRenderObject())
    1353         return 0;
    1354 
    1355     return getAttributeSetForAccessibilityObject(coreObject);
    1356 }
    1357 
    1358 static IntRect textExtents(AtkText* text, gint startOffset, gint length, AtkCoordType coords)
    1359 {
    1360     gchar* textContent = webkit_accessible_text_get_text(text, startOffset, -1);
    1361     gint textLength = g_utf8_strlen(textContent, -1);
    1362 
    1363     // The first case (endOffset of -1) should work, but seems broken for all Gtk+ apps.
    1364     gint rangeLength = length;
    1365     if (rangeLength < 0 || rangeLength > textLength)
    1366         rangeLength = textLength;
    1367     AccessibilityObject* coreObject = core(text);
    1368 
    1369     IntRect extents = coreObject->doAXBoundsForRange(PlainTextRange(startOffset, rangeLength));
    1370     switch (coords) {
    1371     case ATK_XY_SCREEN:
    1372         if (Document* document = coreObject->document())
    1373             extents = document->view()->contentsToScreen(extents);
    1374         break;
    1375     case ATK_XY_WINDOW:
    1376         // No-op
    1377         break;
    1378     }
    1379 
    1380     return extents;
    1381 }
    1382 
    1383 static void webkit_accessible_text_get_character_extents(AtkText* text, gint offset, gint* x, gint* y, gint* width, gint* height, AtkCoordType coords)
    1384 {
    1385     IntRect extents = textExtents(text, offset, 1, coords);
    1386     *x = extents.x();
    1387     *y = extents.y();
    1388     *width = extents.width();
    1389     *height = extents.height();
    1390 }
    1391 
    1392 static void webkit_accessible_text_get_range_extents(AtkText* text, gint startOffset, gint endOffset, AtkCoordType coords, AtkTextRectangle* rect)
    1393 {
    1394     IntRect extents = textExtents(text, startOffset, endOffset - startOffset, coords);
    1395     rect->x = extents.x();
    1396     rect->y = extents.y();
    1397     rect->width = extents.width();
    1398     rect->height = extents.height();
    1399 }
    1400 
    1401 static gint webkit_accessible_text_get_character_count(AtkText* text)
    1402 {
    1403     return accessibilityObjectLength(core(text));
    1404 }
    1405 
    1406 static gint webkit_accessible_text_get_offset_at_point(AtkText* text, gint x, gint y, AtkCoordType coords)
    1407 {
    1408     // FIXME: Use the AtkCoordType
    1409     // TODO: Is it correct to ignore range.length?
    1410     IntPoint pos(x, y);
    1411     PlainTextRange range = core(text)->doAXRangeForPosition(pos);
    1412     return range.start;
    1413 }
    1414 
    1415 static void getSelectionOffsetsForObject(AccessibilityObject* coreObject, VisibleSelection& selection, gint& startOffset, gint& endOffset)
    1416 {
    1417     if (!coreObject->isAccessibilityRenderObject())
    1418         return;
    1419 
    1420     // Early return if the selection doesn't affect the selected node.
    1421     if (!selectionBelongsToObject(coreObject, selection))
    1422         return;
    1423 
    1424     // We need to find the exact start and end positions in the
    1425     // selected node that intersects the selection, to later on get
    1426     // the right values for the effective start and end offsets.
    1427     ExceptionCode ec = 0;
    1428     Position nodeRangeStart;
    1429     Position nodeRangeEnd;
    1430     Node* node = coreObject->node();
    1431     RefPtr<Range> selRange = selection.toNormalizedRange();
    1432 
    1433     // If the selection affects the selected node and its first
    1434     // possible position is also in the selection, we must set
    1435     // nodeRangeStart to that position, otherwise to the selection's
    1436     // start position (it would belong to the node anyway).
    1437     Node* firstLeafNode = node->firstDescendant();
    1438     if (selRange->isPointInRange(firstLeafNode, 0, ec))
    1439         nodeRangeStart = firstPositionInOrBeforeNode(firstLeafNode);
    1440     else
    1441         nodeRangeStart = selRange->startPosition();
    1442 
    1443     // If the selection affects the selected node and its last
    1444     // possible position is also in the selection, we must set
    1445     // nodeRangeEnd to that position, otherwise to the selection's
    1446     // end position (it would belong to the node anyway).
    1447     Node* lastLeafNode = node->lastDescendant();
    1448     if (selRange->isPointInRange(lastLeafNode, lastOffsetInNode(lastLeafNode), ec))
    1449         nodeRangeEnd = lastPositionInOrAfterNode(lastLeafNode);
    1450     else
    1451         nodeRangeEnd = selRange->endPosition();
    1452 
    1453     // Calculate position of the selected range inside the object.
    1454     Position parentFirstPosition = firstPositionInOrBeforeNode(node);
    1455     RefPtr<Range> rangeInParent = Range::create(node->document(), parentFirstPosition, nodeRangeStart);
    1456 
    1457     // Set values for start and end offsets.
    1458     startOffset = TextIterator::rangeLength(rangeInParent.get(), true);
    1459 
    1460     // We need to adjust the offsets for the list item marker.
    1461     RenderObject* renderer = coreObject->renderer();
    1462     if (renderer && renderer->isListItem()) {
    1463         String markerText = toRenderListItem(renderer)->markerTextWithSuffix();
    1464         startOffset += markerText.length();
    1465     }
    1466 
    1467     RefPtr<Range> nodeRange = Range::create(node->document(), nodeRangeStart, nodeRangeEnd);
    1468     endOffset = startOffset + TextIterator::rangeLength(nodeRange.get(), true);
    1469 }
    1470 
    1471 static gint webkit_accessible_text_get_n_selections(AtkText* text)
    1472 {
    1473     AccessibilityObject* coreObject = core(text);
    1474     VisibleSelection selection = coreObject->selection();
    1475 
    1476     // Only range selections are needed for the purpose of this method
    1477     if (!selection.isRange())
    1478         return 0;
    1479 
    1480     // We don't support multiple selections for now, so there's only
    1481     // two possibilities
    1482     // Also, we don't want to do anything if the selection does not
    1483     // belong to the currently selected object. We have to check since
    1484     // there's no way to get the selection for a given object, only
    1485     // the global one (the API is a bit confusing)
    1486     return selectionBelongsToObject(coreObject, selection) ? 1 : 0;
    1487 }
    1488 
    1489 static gchar* webkit_accessible_text_get_selection(AtkText* text, gint selectionNum, gint* startOffset, gint* endOffset)
    1490 {
    1491     // Default values, unless the contrary is proved
    1492     *startOffset = *endOffset = 0;
    1493 
    1494     // WebCore does not support multiple selection, so anything but 0 does not make sense for now.
    1495     if (selectionNum)
    1496         return 0;
    1497 
    1498     // Get the offsets of the selection for the selected object
    1499     AccessibilityObject* coreObject = core(text);
    1500     VisibleSelection selection = coreObject->selection();
    1501     getSelectionOffsetsForObject(coreObject, selection, *startOffset, *endOffset);
    1502 
    1503     // Return 0 instead of "", as that's the expected result for
    1504     // this AtkText method when there's no selection
    1505     if (*startOffset == *endOffset)
    1506         return 0;
    1507 
    1508     return webkit_accessible_text_get_text(text, *startOffset, *endOffset);
    1509 }
    1510 
    1511 static gboolean webkit_accessible_text_add_selection(AtkText* text, gint start_offset, gint end_offset)
    1512 {
    1513     notImplemented();
    1514     return FALSE;
    1515 }
    1516 
    1517 static gboolean webkit_accessible_text_set_selection(AtkText* text, gint selectionNum, gint startOffset, gint endOffset)
    1518 {
    1519     // WebCore does not support multiple selection, so anything but 0 does not make sense for now.
    1520     if (selectionNum)
    1521         return FALSE;
    1522 
    1523     AccessibilityObject* coreObject = core(text);
    1524     if (!coreObject->isAccessibilityRenderObject())
    1525         return FALSE;
    1526 
    1527     // Consider -1 and out-of-bound values and correct them to length
    1528     gint textCount = webkit_accessible_text_get_character_count(text);
    1529     if (startOffset < 0 || startOffset > textCount)
    1530         startOffset = textCount;
    1531     if (endOffset < 0 || endOffset > textCount)
    1532         endOffset = textCount;
    1533 
    1534     // We need to adjust the offsets for the list item marker.
    1535     RenderObject* renderer = coreObject->renderer();
    1536     if (renderer && renderer->isListItem()) {
    1537         String markerText = toRenderListItem(renderer)->markerTextWithSuffix();
    1538         int markerLength = markerText.length();
    1539         if (startOffset < markerLength || endOffset < markerLength)
    1540             return FALSE;
    1541 
    1542         startOffset -= markerLength;
    1543         endOffset -= markerLength;
    1544     }
    1545 
    1546     PlainTextRange textRange(startOffset, endOffset - startOffset);
    1547     VisiblePositionRange range = coreObject->visiblePositionRangeForRange(textRange);
    1548     if (range.isNull())
    1549         return FALSE;
    1550 
    1551     coreObject->setSelectedVisiblePositionRange(range);
    1552     return TRUE;
    1553 }
    1554 
    1555 static gboolean webkit_accessible_text_remove_selection(AtkText* text, gint selectionNum)
    1556 {
    1557     // WebCore does not support multiple selection, so anything but 0 does not make sense for now.
    1558     if (selectionNum)
    1559         return FALSE;
    1560 
    1561     // Do nothing if current selection doesn't belong to the object
    1562     if (!webkit_accessible_text_get_n_selections(text))
    1563         return FALSE;
    1564 
    1565     // Set a new 0-sized selection to the caret position, in order
    1566     // to simulate selection removal (GAIL style)
    1567     gint caretOffset = webkit_accessible_text_get_caret_offset(text);
    1568     return webkit_accessible_text_set_selection(text, selectionNum, caretOffset, caretOffset);
    1569 }
    1570 
    1571 static gboolean webkit_accessible_text_set_caret_offset(AtkText* text, gint offset)
    1572 {
    1573     AccessibilityObject* coreObject = core(text);
    1574 
    1575     if (!coreObject->isAccessibilityRenderObject())
    1576         return FALSE;
    1577 
    1578     RenderObject* renderer = coreObject->renderer();
    1579     if (renderer && renderer->isListItem()) {
    1580         String markerText = toRenderListItem(renderer)->markerTextWithSuffix();
    1581         int markerLength = markerText.length();
    1582         if (offset < markerLength)
    1583             return FALSE;
    1584 
    1585         // We need to adjust the offset for list items.
    1586         offset -= markerLength;
    1587     }
    1588 
    1589     PlainTextRange textRange(offset, 0);
    1590     VisiblePositionRange range = coreObject->visiblePositionRangeForRange(textRange);
    1591     if (range.isNull())
    1592         return FALSE;
    1593 
    1594     coreObject->setSelectedVisiblePositionRange(range);
    1595     return TRUE;
    1596 }
    1597 
    1598 static void atk_text_interface_init(AtkTextIface* iface)
    1599 {
    1600     iface->get_text = webkit_accessible_text_get_text;
    1601     iface->get_text_after_offset = webkit_accessible_text_get_text_after_offset;
    1602     iface->get_text_at_offset = webkit_accessible_text_get_text_at_offset;
    1603     iface->get_character_at_offset = webkit_accessible_text_get_character_at_offset;
    1604     iface->get_text_before_offset = webkit_accessible_text_get_text_before_offset;
    1605     iface->get_caret_offset = webkit_accessible_text_get_caret_offset;
    1606     iface->get_run_attributes = webkit_accessible_text_get_run_attributes;
    1607     iface->get_default_attributes = webkit_accessible_text_get_default_attributes;
    1608     iface->get_character_extents = webkit_accessible_text_get_character_extents;
    1609     iface->get_range_extents = webkit_accessible_text_get_range_extents;
    1610     iface->get_character_count = webkit_accessible_text_get_character_count;
    1611     iface->get_offset_at_point = webkit_accessible_text_get_offset_at_point;
    1612     iface->get_n_selections = webkit_accessible_text_get_n_selections;
    1613     iface->get_selection = webkit_accessible_text_get_selection;
    1614 
    1615     // set methods
    1616     iface->add_selection = webkit_accessible_text_add_selection;
    1617     iface->remove_selection = webkit_accessible_text_remove_selection;
    1618     iface->set_selection = webkit_accessible_text_set_selection;
    1619     iface->set_caret_offset = webkit_accessible_text_set_caret_offset;
    1620 }
    1621 
    1622796// Table
    1623797
     
    1786960    AtkObject* columnHeader = atk_table_get_column_header(table, column);
    1787961    if (columnHeader && ATK_IS_TEXT(columnHeader))
    1788         return webkit_accessible_text_get_text(ATK_TEXT(columnHeader), 0, -1);
     962        return webkitAccessibleTextGetText(ATK_TEXT(columnHeader), 0, -1);
    1789963
    1790964    return 0;
     
    1795969    AtkObject* rowHeader = atk_table_get_row_header(table, row);
    1796970    if (rowHeader && ATK_IS_TEXT(rowHeader))
    1797         return webkit_accessible_text_get_text(ATK_TEXT(rowHeader), 0, -1);
     971        return webkitAccessibleTextGetText(ATK_TEXT(rowHeader), 0, -1);
    1798972
    1799973    return 0;
     
    1821995    {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleSelectionInterfaceInit), 0, 0},
    1822996    {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleEditableTextInterfaceInit), 0, 0},
    1823     {(GInterfaceInitFunc)atk_text_interface_init,
    1824      (GInterfaceFinalizeFunc) 0, 0},
     997    {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleTextInterfaceInit), 0, 0},
    1825998    {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleComponentInterfaceInit), 0, 0},
    1826999    {reinterpret_cast<GInterfaceInitFunc>(webkitAccessibleImageInterfaceInit), 0, 0},
Note: See TracChangeset for help on using the changeset viewer.