⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 180726 in webkit


Ignore:
Timestamp:
Feb 26, 2015, 9:51:31 PM (11 years ago)
Author:
rniwa@webkit.org
Message:

isEditablePosition and related functions shouldn't move position out of table
https://bugs.webkit.org/show_bug.cgi?id=129200

Reviewed by Darin Adler.

Source/WebCore:

This patch removes the legacy editing position for elements display: table in its computed style.
Previously, we used (table, 0) and (table, !0) to denote positions immediately before and after
such an element for historical reasons. This forced us to update the style tree before computing
the editability of a position because we have to check the editability of the position outside
the element with display: table if the position was using such a legacy editing position.
e.g. if a table was not editable (contenteditable=false), the position before the table (table, 0)
should still be considered editable if the parent node of the table was editable.

This patch replaces such a legacy editing position by using modern position types:
PositionIsBeforeAnchor and PositionIsAfterAnchor.

No new tests since there should be no change in the user perceived editing operations.

  • dom/Position.cpp:

(WebCore::Position::previous): Setup the node and the offset correctly when the original position's
type is PositionIsBeforeAnchor. Also return a position before or after node when the node we found
is "atomic" (e.g. input, img, br, etc...) or it's a table. This avoids creating a legacy editing
position inside a table.
(WebCore::Position::next): Ditto.
(WebCore::Position::atStartOfTree): Use atFirstEditingPositionForNode, which takes care of all types
of positions.
(WebCore::Position::atEndOfTree): Ditto.
(WebCore::Position::downstream): Return a position before a node instead of a legacy editing position
for an atomic element or a table element as done in the equivalent code in Position::upstream.
(WebCore::Position::isCandidate): Don't treat a position inside a table to be a candidate. e.g.
(table, 1) when there are more than two children of the table.

  • dom/PositionIterator.cpp:

(WebCore::PositionIterator::operator Position): PositionIterator internally uses legacy editing
positions. So convert it to a modern position by returning a position before or after a table here.

  • editing/ApplyBlockElementCommand.cpp:

(WebCore::ApplyBlockElementCommand::formatSelection): Check that the unsplittable element we found
is actually empty before executing the simple code path for an empty unsplittable element. Without
this check, block formatting a table element will fail.

  • editing/htmlediting.cpp:

(WebCore::isEditablePosition): Use containerNode instead of deprecatedNode because the editability
of a position before or after an element is determined by its parent, not the element itself.
(WebCore::isAtUnsplittableElement): Ditto.
(WebCore::isRichlyEditablePosition): Ditto. Removed the code that moved the starting node out of
an element with display: table. This is the code removal for which this patch was made.
(WebCore::editableRootForPosition): Ditto.

LayoutTests:

Rebaselined a test. There is no visual difference.

  • platform/mac/editing/inserting/5058163-1-expected.txt:
Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r180724 r180726  
     12015-02-26  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        isEditablePosition and related functions shouldn't move position out of table
     4        https://bugs.webkit.org/show_bug.cgi?id=129200
     5
     6        Reviewed by Darin Adler.
     7
     8        Rebaselined a test. There is no visual difference.
     9
     10        * platform/mac/editing/inserting/5058163-1-expected.txt:
     11
    1122015-02-26  Brent Fulgham  <bfulgham@apple.com>
    213
  • trunk/LayoutTests/platform/mac/editing/inserting/5058163-1-expected.txt

    r177774 r180726  
    1414                RenderText {#text} at (1,1) size 476x18
    1515                  text run at (1,1) width 476: "There should be two empty paragraphs after this table and before the next."
    16         RenderBlock (anonymous) at (0,26) size 784x36
     16        RenderBlock {DIV} at (0,26) size 784x18
    1717          RenderBR {BR} at (0,0) size 0x18
    18           RenderBR {BR} at (0,18) size 0x18
     18        RenderBlock (anonymous) at (0,44) size 784x18
     19          RenderBR {BR} at (0,0) size 0x18
    1920        RenderTable {TABLE} at (0,62) size 280x26 [border: (1px solid #AAAAAA)]
    2021          RenderTableSection {TBODY} at (1,1) size 278x24
  • trunk/Source/WebCore/ChangeLog

    r180720 r180726  
     12015-02-26  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        isEditablePosition and related functions shouldn't move position out of table
     4        https://bugs.webkit.org/show_bug.cgi?id=129200
     5
     6        Reviewed by Darin Adler.
     7
     8        This patch removes the legacy editing position for elements display: table in its computed style.
     9        Previously, we used (table, 0) and (table, !0) to denote positions immediately before and after
     10        such an element for historical reasons. This forced us to update the style tree before computing
     11        the editability of a position because we have to check the editability of the position outside
     12        the element with display: table if the position was using such a legacy editing position.
     13        e.g. if a table was not editable (contenteditable=false), the position before the table (table, 0)
     14        should still be considered editable if the parent node of the table was editable.
     15
     16        This patch replaces such a legacy editing position by using modern position types:
     17        PositionIsBeforeAnchor and PositionIsAfterAnchor.
     18
     19        No new tests since there should be no change in the user perceived editing operations.
     20
     21        * dom/Position.cpp:
     22        (WebCore::Position::previous): Setup the node and the offset correctly when the original position's
     23        type is PositionIsBeforeAnchor. Also return a position before or after node when the node we found
     24        is "atomic" (e.g. input, img, br, etc...) or it's a table. This avoids creating a legacy editing
     25        position inside a table.
     26        (WebCore::Position::next): Ditto.
     27        (WebCore::Position::atStartOfTree): Use atFirstEditingPositionForNode, which takes care of all types
     28        of positions.
     29        (WebCore::Position::atEndOfTree): Ditto.
     30        (WebCore::Position::downstream): Return a position before a node instead of a legacy editing position
     31        for an atomic element or a table element as done in the equivalent code in Position::upstream.
     32        (WebCore::Position::isCandidate): Don't treat a position inside a table to be a candidate. e.g.
     33        (table, 1) when there are more than two children of the table.
     34
     35        * dom/PositionIterator.cpp:
     36        (WebCore::PositionIterator::operator Position): PositionIterator internally uses legacy editing
     37        positions. So convert it to a modern position by returning a position before or after a table here.
     38        * editing/ApplyBlockElementCommand.cpp:
     39        (WebCore::ApplyBlockElementCommand::formatSelection): Check that the unsplittable element we found
     40        is actually empty before executing the simple code path for an empty unsplittable element. Without
     41        this check, block formatting a table element will fail.
     42
     43        * editing/htmlediting.cpp:
     44        (WebCore::isEditablePosition): Use containerNode instead of deprecatedNode because the editability
     45        of a position before or after an element is determined by its parent, not the element itself.
     46        (WebCore::isAtUnsplittableElement): Ditto.
     47        (WebCore::isRichlyEditablePosition): Ditto. Removed the code that moved the starting node out of
     48        an element with display: table. This is the code removal for which this patch was made.
     49        (WebCore::editableRootForPosition): Ditto.
     50
    1512015-02-26  Timothy Horton  <timothy_horton@apple.com>
    252
  • trunk/Source/WebCore/dom/Position.cpp

    r180213 r180726  
    309309    ASSERT(offset >= 0);
    310310
     311    if (anchorType() == PositionIsBeforeAnchor) {
     312        node = containerNode();
     313        offset = computeOffsetInContainerNode();
     314    }
     315
    311316    if (offset > 0) {
    312317        if (Node* child = node->traverseToChildAt(offset - 1))
     
    332337        return *this;
    333338
     339    if (positionBeforeOrAfterNodeIsCandidate(node))
     340        return positionBeforeNode(node);
     341
     342    Node* previousSibling = node->previousSibling();
     343    if (previousSibling && positionBeforeOrAfterNodeIsCandidate(previousSibling))
     344        return positionAfterNode(previousSibling);
     345
    334346    return createLegacyEditingPosition(parent, node->computeNodeIndex());
    335347}
     
    346358    // FIXME: Negative offsets shouldn't be allowed. We should catch this earlier.
    347359    ASSERT(offset >= 0);
     360
     361    if (anchorType() == PositionIsAfterAnchor) {
     362        node = containerNode();
     363        offset = computeOffsetInContainerNode();
     364    }
    348365
    349366    Node* child = node->traverseToChildAt(offset);
     
    363380    if (!parent)
    364381        return *this;
     382
     383    if (isRenderedTable(node) || editingIgnoresContent(node))
     384        return positionAfterNode(node);
     385
     386    Node* nextSibling = node->nextSibling();
     387    if (nextSibling && positionBeforeOrAfterNodeIsCandidate(nextSibling))
     388        return positionBeforeNode(nextSibling);
    365389
    366390    return createLegacyEditingPosition(parent, node->computeNodeIndex() + 1);
     
    453477    if (isNull())
    454478        return true;
    455     return !findParent(deprecatedNode()) && m_offset <= 0;
     479    return !findParent(containerNode()) && atFirstEditingPositionForNode();
    456480}
    457481
     
    460484    if (isNull())
    461485        return true;
    462     return !findParent(deprecatedNode()) && m_offset >= lastOffsetForEditing(deprecatedNode());
     486    return !findParent(containerNode()) && atLastEditingPositionForNode();
    463487}
    464488
     
    755779        if (editingIgnoresContent(currentNode) || isRenderedTable(currentNode)) {
    756780            if (currentPos.offsetInLeafNode() <= renderer->caretMinOffset())
    757                 return createLegacyEditingPosition(currentNode, renderer->caretMinOffset());
     781                return positionBeforeNode(currentNode);
    758782            continue;
    759783        }
     
    932956        return !nodeIsUserSelectNone(deprecatedNode()) && downcast<RenderText>(*renderer).containsCaretOffset(m_offset);
    933957
    934     if (isRenderedTable(deprecatedNode()) || editingIgnoresContent(deprecatedNode()))
    935         return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
     958    if (positionBeforeOrAfterNodeIsCandidate(deprecatedNode())) {
     959        return ((atFirstEditingPositionForNode() && m_anchorType == PositionIsBeforeAnchor)
     960            || (atLastEditingPositionForNode() && m_anchorType == PositionIsAfterAnchor))
     961            && !nodeIsUserSelectNone(deprecatedNode()->parentNode());
     962    }
    936963
    937964    if (m_anchorNode->hasTagName(htmlTag))
  • trunk/Source/WebCore/dom/PositionIterator.cpp

    r174403 r180726  
    4444        ASSERT(m_nodeAfterPositionInAnchor->parentNode() == m_anchorNode);
    4545        // FIXME: This check is inadaquete because any ancestor could be ignored by editing
    46         if (editingIgnoresContent(m_nodeAfterPositionInAnchor->parentNode()))
     46        if (positionBeforeOrAfterNodeIsCandidate(m_anchorNode))
    4747            return positionBeforeNode(m_anchorNode);
    4848        return positionInParentBeforeNode(m_nodeAfterPositionInAnchor);
    4949    }
     50    if (positionBeforeOrAfterNodeIsCandidate(m_anchorNode))
     51        return atStartOfNode() ? positionBeforeNode(m_anchorNode) : positionAfterNode(m_anchorNode);
    5052    if (m_anchorNode->hasChildNodes())
    5153        return lastPositionInOrAfterNode(m_anchorNode);
  • trunk/Source/WebCore/editing/ApplyBlockElementCommand.cpp

    r174225 r180726  
    104104    // and there's nothing to move.
    105105    Position start = startOfSelection.deepEquivalent().downstream();
    106     if (isAtUnsplittableElement(start)) {
     106    if (isAtUnsplittableElement(start) && startOfParagraph(start) == endOfParagraph(endOfSelection)) {
    107107        RefPtr<Element> blockquote = createBlockElement();
    108108        insertNodeAt(blockquote, start);
  • trunk/Source/WebCore/editing/htmlediting.cpp

    r179143 r180726  
    144144bool isEditablePosition(const Position& p, EditableType editableType, EUpdateStyle updateStyle)
    145145{
    146     Node* node = p.deprecatedNode();
     146    Node* node = p.containerNode();
    147147    if (!node)
    148148        return false;
     
    152152        ASSERT(updateStyle == DoNotUpdateStyle);
    153153
    154     if (node->renderer() && node->renderer()->isTable())
    155         node = node->parentNode();
    156 
    157154    return node->hasEditableStyle(editableType);
    158155}
     
    160157bool isAtUnsplittableElement(const Position& pos)
    161158{
    162     Node* node = pos.deprecatedNode();
     159    Node* node = pos.containerNode();
    163160    return (node == editableRootForPosition(pos) || node == enclosingNodeOfType(pos, &isTableCell));
    164161}
     
    167164bool isRichlyEditablePosition(const Position& p, EditableType editableType)
    168165{
    169     Node* node = p.deprecatedNode();
     166    Node* node = p.containerNode();
    170167    if (!node)
    171168        return false;
    172        
    173     if (node->renderer() && node->renderer()->isTable())
    174         node = node->parentNode();
    175    
     169
    176170    return node->hasRichlyEditableStyle(editableType);
    177171}
     
    182176    if (!node)
    183177        return 0;
    184        
    185     if (node->renderer() && node->renderer()->isTable())
    186         node = node->parentNode();
    187    
     178
    188179    return node->rootEditableElement(editableType);
    189180}
  • trunk/Source/WebCore/editing/htmlediting.h

    r179861 r180726  
    121121bool isNonTableCellHTMLBlockElement(const Node*);
    122122
     123inline bool positionBeforeOrAfterNodeIsCandidate(Node* node)
     124{
     125    return isRenderedTable(node) || editingIgnoresContent(node);
     126}
     127
    123128WEBCORE_EXPORT TextDirection directionOfEnclosingBlock(const Position&);
    124129
Note: See TracChangeset for help on using the changeset viewer.