Changeset 126026 in webkit


Ignore:
Timestamp:
Aug 20, 2012 7:50:24 AM (12 years ago)
Author:
allan.jensen@nokia.com
Message:

[TouchAdjustment] Adjust to word or selection
https://bugs.webkit.org/show_bug.cgi?id=94449

Reviewed by Antonio Gomes.

Source/WebCore:

Makes each separate word a separate subtarget when context menu triggers
selections, and only the selected part of a partial selected node a
target when selections are not overridden.

Test: touchadjustment/context-menu-text-subtargets.html

  • page/TouchAdjustment.cpp:

(TouchAdjustment):
(WebCore::TouchAdjustment::providesContextMenuItems):
(WebCore::TouchAdjustment::appendQuadsToSubtargetList):
(WebCore::TouchAdjustment::appendBasicSubtargetsForNode):
(WebCore::TouchAdjustment::appendContextSubtargetsForNode):
(WebCore::TouchAdjustment::compileSubtargetList):
(WebCore::findBestClickableCandidate):
(WebCore::findBestContextMenuCandidate):

LayoutTests:

Tests that touch-adjustment can adjust to the right subtargets within text-nodes.

  • touchadjustment/context-menu-select-text.html:
  • touchadjustment/context-menu-text-subtargets-expected.txt: Added.
  • touchadjustment/context-menu-text-subtargets.html: Added.
  • touchadjustment/resources/touchadjustment.js:

(pointToString):
(shouldBeWithin):

Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r126025 r126026  
     12012-08-20  Allan Sandfeld Jensen  <allan.jensen@nokia.com>
     2
     3        [TouchAdjustment] Adjust to word or selection
     4        https://bugs.webkit.org/show_bug.cgi?id=94449
     5
     6        Reviewed by Antonio Gomes.
     7
     8        Tests that touch-adjustment can adjust to the right subtargets within text-nodes.
     9
     10        * touchadjustment/context-menu-select-text.html:
     11        * touchadjustment/context-menu-text-subtargets-expected.txt: Added.
     12        * touchadjustment/context-menu-text-subtargets.html: Added.
     13        * touchadjustment/resources/touchadjustment.js:
     14        (pointToString):
     15        (shouldBeWithin):
     16
    1172012-08-20  'Pavel Feldman'  <pfeldman@chromium.org>
    218
  • trunk/LayoutTests/touchadjustment/context-menu-select-text.html

    r125898 r126026  
    22<html>
    33<head>
    4     <title>Touch Adjustment : Adjust context-menu to selectable words - bug 94101</title>
     4    <title>Touch Adjustment : Adjust context-menu to selectable text - bug 94101</title>
    55    <script src="../fast/js/resources/js-test-pre.js"></script>
    66    <script src="resources/touchadjustment.js"></script>
  • trunk/LayoutTests/touchadjustment/resources/touchadjustment.js

    r125898 r126026  
    2525}
    2626
     27function boundsToString(bounds)
     28{
     29    return "("+bounds.left+","+bounds.top+")x("+bounds.width+","+bounds.height+")";
     30}
     31
     32function pointToString(point)
     33{
     34    return "("+point.x+","+point.y+")";
     35}
     36
     37
    2738function shouldBeNode(adjustedNode, targetNode) {
    2839    if (typeof targetNode == "string") {
     
    4354    }
    4455}
     56
     57function shouldBeWithin(adjustedPoint, targetArea) {
     58    if (adjustedPoint.x >= targetArea.left && adjustedPoint.y >= targetArea.top
     59        && adjustedPoint.x <= (targetArea.left + targetArea.width)
     60        && adjustedPoint.y <= (targetArea.top + targetArea.height)) {
     61        testPassed("adjusted point was within " + boundsToString(targetArea));
     62    } else {
     63        testFailed("adjusted node should be within " + boundsToString(targetArea)  + ". Was " + pointToString(adjustedPoint));
     64    }
     65}
     66
    4567
    4668function testTouchPoint(touchpoint, targetNode, allowTextNodes)
  • trunk/Source/WebCore/ChangeLog

    r126021 r126026  
     12012-08-20  Allan Sandfeld Jensen  <allan.jensen@nokia.com>
     2
     3        [TouchAdjustment] Adjust to word or selection
     4        https://bugs.webkit.org/show_bug.cgi?id=94449
     5
     6        Reviewed by Antonio Gomes.
     7
     8        Makes each separate word a separate subtarget when context menu triggers
     9        selections, and only the selected part of a partial selected node a
     10        target when selections are not overridden.
     11
     12        Test: touchadjustment/context-menu-text-subtargets.html
     13
     14        * page/TouchAdjustment.cpp:
     15        (TouchAdjustment):
     16        (WebCore::TouchAdjustment::providesContextMenuItems):
     17        (WebCore::TouchAdjustment::appendQuadsToSubtargetList):
     18        (WebCore::TouchAdjustment::appendBasicSubtargetsForNode):
     19        (WebCore::TouchAdjustment::appendContextSubtargetsForNode):
     20        (WebCore::TouchAdjustment::compileSubtargetList):
     21        (WebCore::findBestClickableCandidate):
     22        (WebCore::findBestContextMenuCandidate):
     23
    1242012-08-20  Xan Lopez  <xlopez@igalia.com>
    225
  • trunk/Source/WebCore/page/TouchAdjustment.cpp

    r125898 r126026  
    3636#include "RenderObject.h"
    3737#include "RenderStyle.h"
     38#include "RenderText.h"
    3839#include "ShadowRoot.h"
     40#include "Text.h"
     41#include "TextBreakIterator.h"
    3942
    4043namespace WebCore {
     
    6366typedef Vector<SubtargetGeometry> SubtargetGeometryList;
    6467typedef bool (*NodeFilter)(Node*);
     68typedef void (*AppendSubtargetsForNode)(Node*, SubtargetGeometryList&);
    6569typedef float (*DistanceFunction)(const IntPoint&, const IntRect&, const SubtargetGeometry&);
    6670
     
    102106        return true;
    103107    if (node->renderer()->canBeSelectionLeaf()) {
    104         // If the context menu gesture will trigger a selection all selectable nodes are targets.
    105         // FIXME: To improve the adjusted point, each individual word should be a separate subtarget,
    106         // see for example FatFingers::checkForText() in WebKit/blackberry.
     108        // If the context menu gesture will trigger a selection all selectable nodes are valid targets.
    107109        if (node->renderer()->frame()->editor()->behavior().shouldSelectOnContextualMenuClick())
    108110            return true;
    109         // FIXME: A selected text might only be partially selected, and we should only append
    110         // the selected subtargets of it in appendSubtargetsForNodeToList().
     111        // Only the selected part of the renderer is a valid target, but this will be corrected in
     112        // appendContextSubtargetsForNode.
    111113        if (node->renderer()->selectionState() != RenderObject::SelectionNone)
    112114            return true;
     
    115117}
    116118
    117 static inline void appendSubtargetsForNodeToList(Node* node, SubtargetGeometryList& subtargets)
    118 {
    119     // Since the node is a result of a hit test, we are already ensured it has a renderer.
    120     ASSERT(node->renderer());
    121 
    122     Vector<FloatQuad> quads;
    123     node->renderer()->absoluteQuads(quads);
    124 
     119static inline void appendQuadsToSubtargetList(Vector<FloatQuad>& quads, Node* node, SubtargetGeometryList& subtargets)
     120{
    125121    Vector<FloatQuad>::const_iterator it = quads.begin();
    126122    const Vector<FloatQuad>::const_iterator end = quads.end();
    127123    for (; it != end; ++it)
    128124        subtargets.append(SubtargetGeometry(node, *it));
     125}
     126
     127static inline void appendBasicSubtargetsForNode(Node* node, SubtargetGeometryList& subtargets)
     128{
     129    // Since the node is a result of a hit test, we are already ensured it has a renderer.
     130    ASSERT(node->renderer());
     131
     132    Vector<FloatQuad> quads;
     133    node->renderer()->absoluteQuads(quads);
     134
     135    appendQuadsToSubtargetList(quads, node, subtargets);
     136}
     137
     138static inline void appendContextSubtargetsForNode(Node* node, SubtargetGeometryList& subtargets)
     139{
     140    // This is a variant of appendBasicSubtargetsForNode that adds special subtargets for
     141    // selected or auto-selectable parts of text nodes.
     142    ASSERT(node->renderer());
     143
     144    if (!node->isTextNode())
     145        return appendBasicSubtargetsForNode(node, subtargets);
     146
     147    Text* textNode = static_cast<WebCore::Text*>(node);
     148    RenderText* textRenderer = static_cast<RenderText*>(textNode->renderer());
     149
     150    if (textRenderer->frame()->editor()->behavior().shouldSelectOnContextualMenuClick()) {
     151        // Make subtargets out of every word.
     152        String textValue = textNode->data();
     153        TextBreakIterator* wordIterator = wordBreakIterator(textValue.characters(), textValue.length());
     154        int lastOffset = textBreakFirst(wordIterator);
     155        if (lastOffset == -1)
     156            return;
     157        int offset;
     158        while ((offset = textBreakNext(wordIterator)) != -1) {
     159            if (isWordTextBreak(wordIterator)) {
     160                Vector<FloatQuad> quads;
     161                textRenderer->absoluteQuadsForRange(quads, lastOffset, offset);
     162                appendQuadsToSubtargetList(quads, textNode, subtargets);
     163            }
     164            lastOffset = offset;
     165        }
     166    } else {
     167        // Make subtargets out of only the selected part of the text.
     168        ASSERT(textRenderer->selectionState() != RenderObject::SelectionNone);
     169        int startPos, endPos;
     170        switch (textRenderer->selectionState()) {
     171        case RenderObject::SelectionInside:
     172            startPos = 0;
     173            endPos = textRenderer->textLength();
     174            break;
     175        case RenderObject::SelectionStart:
     176            textRenderer->selectionStartEnd(startPos, endPos);
     177            endPos = textRenderer->textLength();
     178            break;
     179        case RenderObject::SelectionEnd:
     180            textRenderer->selectionStartEnd(startPos, endPos);
     181            startPos = 0;
     182            break;
     183        case RenderObject::SelectionBoth:
     184            textRenderer->selectionStartEnd(startPos, endPos);
     185            break;
     186        default:
     187            appendBasicSubtargetsForNode(node, subtargets);
     188            return;
     189        }
     190        Vector<FloatQuad> quads;
     191        textRenderer->absoluteQuadsForRange(quads, startPos, endPos);
     192        appendQuadsToSubtargetList(quads, textNode, subtargets);
     193    }
    129194}
    130195
     
    149214
    150215// Compiles a list of subtargets of all the relevant target nodes.
    151 void compileSubtargetList(const NodeList& intersectedNodes, SubtargetGeometryList& subtargets, NodeFilter nodeFilter)
     216void compileSubtargetList(const NodeList& intersectedNodes, SubtargetGeometryList& subtargets, NodeFilter nodeFilter, AppendSubtargetsForNode appendSubtargetsForNode)
    152217{
    153218    // Find candidates responding to tap gesture events in O(n) time.
     
    202267        if (ancestorsToRespondersSet.contains(respondingNode))
    203268            continue;
    204         appendSubtargetsForNodeToList(candidate, subtargets);
     269        appendSubtargetsForNode(candidate, subtargets);
    205270    }
    206271}
     
    409474    IntRect targetArea;
    410475    TouchAdjustment::SubtargetGeometryList subtargets;
    411     TouchAdjustment::compileSubtargetList(nodeList, subtargets, TouchAdjustment::nodeRespondsToTapGesture);
     476    TouchAdjustment::compileSubtargetList(nodeList, subtargets, TouchAdjustment::nodeRespondsToTapGesture, TouchAdjustment::appendBasicSubtargetsForNode);
    412477    return TouchAdjustment::findNodeWithLowestDistanceMetric(targetNode, targetPoint, targetArea, touchHotspot, touchArea, subtargets, TouchAdjustment::hybridDistanceFunction);
    413478}
     
    417482    IntRect targetArea;
    418483    TouchAdjustment::SubtargetGeometryList subtargets;
    419     TouchAdjustment::compileSubtargetList(nodeList, subtargets, TouchAdjustment::providesContextMenuItems);
     484    TouchAdjustment::compileSubtargetList(nodeList, subtargets, TouchAdjustment::providesContextMenuItems, TouchAdjustment::appendContextSubtargetsForNode);
    420485    return TouchAdjustment::findNodeWithLowestDistanceMetric(targetNode, targetPoint, targetArea, touchHotspot, touchArea, subtargets, TouchAdjustment::hybridDistanceFunction);
    421486}
Note: See TracChangeset for help on using the changeset viewer.