Changeset 67320 in webkit


Ignore:
Timestamp:
Sep 12, 2010 4:16:14 AM (14 years ago)
Author:
commit-queue@webkit.org
Message:

2010-09-12 Mario Sanchez Prada <msanchez@igalia.com>

Reviewed by Martin Robinson.

[Gtk] get_n_selections and get_selection fail when selecting text across object boundaries
https://bugs.webkit.org/show_bug.cgi?id=26991

Fix AtkText getNSelections() and getSelection() to work properly

  • accessibility/gtk/AccessibilityObjectWrapperAtk.cpp: (selectionBelongsToObject): Check that both the selection intersects the node AND that the selection is not just "touching" one of the boundaries for the selected node. We want to check whether the node is actually inside the region, at least partially (getSelectionOffsetsForObject): New function to get the start and end offsets of a selection for a given accessible object. (webkit_accessible_text_get_selection): Return zero when both start and end offsets are equal, following the lead of GAIL.
Location:
trunk/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r67316 r67320  
     12010-09-12  Mario Sanchez Prada  <msanchez@igalia.com>
     2
     3        Reviewed by Martin Robinson.
     4
     5        [Gtk] get_n_selections and get_selection fail when selecting text across object boundaries
     6        https://bugs.webkit.org/show_bug.cgi?id=26991
     7
     8        Fix AtkText getNSelections() and getSelection() to work properly
     9
     10        * accessibility/gtk/AccessibilityObjectWrapperAtk.cpp:
     11        (selectionBelongsToObject): Check that both the selection intersects
     12        the node AND that the selection is not just "touching" one of the
     13        boundaries for the selected node. We want to check whether the
     14        node is actually inside the region, at least partially
     15        (getSelectionOffsetsForObject): New function to get the start and
     16        end offsets of a selection for a given accessible object.
     17        (webkit_accessible_text_get_selection): Return zero when both
     18        start and end offsets are equal, following the lead of GAIL.
     19
    1202010-09-11  Adam Barth  <abarth@webkit.org>
    221
  • trunk/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp

    r66964 r67320  
    5959#include "RenderText.h"
    6060#include "TextEncoding.h"
     61#include "TextIterator.h"
    6162#include <wtf/text/CString.h>
    6263#include <wtf/text/AtomicString.h>
     
    13431344        return false;
    13441345
    1345     Node* node = static_cast<AccessibilityRenderObject*>(coreObject)->renderer()->node();
    1346     return node == selection.base().containerNode();
     1346    RefPtr<Range> range = selection.toNormalizedRange();
     1347    if (!range)
     1348        return false;
     1349
     1350    // We want to check that both the selection intersects the node
     1351    // AND that the selection is not just "touching" one of the
     1352    // boundaries for the selected node. We want to check whether the
     1353    // node is actually inside the region, at least partially
     1354    Node* node = coreObject->node();
     1355    Node* lastDescendant = node->lastDescendant();
     1356    ExceptionCode ec = 0;
     1357    return (range->intersectsNode(node, ec)
     1358            && (range->endContainer() != node || range->endOffset())
     1359            && (range->startContainer() != lastDescendant || range->startOffset() != lastOffsetInNode(lastDescendant)));
     1360}
     1361
     1362static void getSelectionOffsetsForObject(AccessibilityObject* coreObject, VisibleSelection& selection, gint& startOffset, gint& endOffset)
     1363{
     1364    if (!coreObject->isAccessibilityRenderObject())
     1365        return;
     1366
     1367    // Early return if the selection doesn't affect the selected node
     1368    if (!selectionBelongsToObject(coreObject, selection))
     1369        return;
     1370
     1371    // We need to find the exact start and end positions in the
     1372    // selected node that intersects the selection, to later on get
     1373    // the right values for the effective start and end offsets
     1374    ExceptionCode ec = 0;
     1375    Position nodeRangeStart;
     1376    Position nodeRangeEnd;
     1377    Node* node = coreObject->node();
     1378    RefPtr<Range> selRange = selection.toNormalizedRange();
     1379
     1380    // If the selection affects the selected node and its first
     1381    // possible position is also in the selection, we must set
     1382    // nodeRangeStart to that position, otherwise to the selection's
     1383    // start position (it would belong to the node anyway)
     1384    Node* firstLeafNode = node->firstDescendant();
     1385    if (selRange->isPointInRange(firstLeafNode, 0, ec))
     1386        nodeRangeStart = firstPositionInNode(firstLeafNode);
     1387    else
     1388        nodeRangeStart = selRange->startPosition();
     1389
     1390    // If the selection affects the selected node and its last
     1391    // possible position is also in the selection, we must set
     1392    // nodeRangeEnd to that position, otherwise to the selection's
     1393    // end position (it would belong to the node anyway)
     1394    Node* lastLeafNode = node->lastDescendant();
     1395    if (selRange->isPointInRange(lastLeafNode, lastOffsetInNode(lastLeafNode), ec))
     1396        nodeRangeEnd = lastPositionInNode(lastLeafNode);
     1397    else
     1398        nodeRangeEnd = selRange->endPosition();
     1399
     1400    // Set preliminar values for start and end offsets
     1401    startOffset = nodeRangeStart.offsetInContainerNode();
     1402    endOffset = nodeRangeEnd.offsetInContainerNode();
     1403
     1404    // If the end node is different then the start node, iterate over
     1405    // those among them to build the effective value for endOffset
     1406    if (nodeRangeStart.anchorNode() != nodeRangeEnd.anchorNode()) {
     1407        RefPtr<Range> nodeRange = Range::create(node->document(), nodeRangeStart, positionBeforeNode(nodeRangeEnd.anchorNode()));
     1408        for (TextIterator it(nodeRange.get()); !it.atEnd(); it.advance()) {
     1409            RefPtr<Range> range = it.range();
     1410            if (range->startContainer()->isTextNode())
     1411                endOffset += range->endOffset();
     1412        }
     1413    }
    13471414}
    13481415
     
    13511418    AccessibilityObject* coreObject = core(text);
    13521419    VisibleSelection selection = coreObject->selection();
     1420
     1421    // Only range selections are needed for the purpose of this method
     1422    if (!selection.isRange())
     1423        return 0;
    13531424
    13541425    // We don't support multiple selections for now, so there's only
     
    13611432}
    13621433
    1363 static gchar* webkit_accessible_text_get_selection(AtkText* text, gint selection_num, gint* start_offset, gint* end_offset)
    1364 {
     1434static gchar* webkit_accessible_text_get_selection(AtkText* text, gint selectionNum, gint* startOffset, gint* endOffset)
     1435{
     1436    // Default values, unless the contrary is proved
     1437    *startOffset = *endOffset = 0;
     1438
     1439    // WebCore does not support multiple selection, so anything but 0 does not make sense for now.
     1440    if (selectionNum)
     1441        return 0;
     1442
     1443    // Get the offsets of the selection for the selected object
    13651444    AccessibilityObject* coreObject = core(text);
    13661445    VisibleSelection selection = coreObject->selection();
    1367 
    1368     // WebCore does not support multiple selection, so anything but 0 does not make sense for now.
    1369     // Also, we don't want to do anything if the selection does not
    1370     // belong to the currently selected object. We have to check since
    1371     // there's no way to get the selection for a given object, only
    1372     // the global one (the API is a bit confusing)
    1373     if (selection_num != 0 || !selectionBelongsToObject(coreObject, selection)) {
    1374         *start_offset = *end_offset = 0;
    1375         return 0;
    1376     }
    1377 
    1378     *start_offset = selection.start().offsetInContainerNode();
    1379     *end_offset = selection.end().offsetInContainerNode();
    1380 
    1381     return webkit_accessible_text_get_text(text, *start_offset, *end_offset);
     1446    getSelectionOffsetsForObject(coreObject, selection, *startOffset, *endOffset);
     1447
     1448    // Return 0 instead of "", as that's the expected result for
     1449    // this AtkText method when there's no selection
     1450    if (*startOffset == *endOffset)
     1451        return 0;
     1452
     1453    return webkit_accessible_text_get_text(text, *startOffset, *endOffset);
    13821454}
    13831455
Note: See TracChangeset for help on using the changeset viewer.