[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc
morrita at google.com
morrita at google.com
Wed Dec 22 11:50:06 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit 1632a1f66c490773d8a41a03386995cf0dd7cbac
Author: morrita at google.com <morrita at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Aug 9 11:40:10 2010 +0000
2010-05-20 MORITA Hajime <morrita at google.com>
Reviewed by Ojan Vafai.
<http://webkit.org/b/36360>
Double clicking page's first editable inline element cannot select a word.
<http://webkit.org/b/36359>
Double clicking page's last editable inline element causes assertion failure.
* editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt: Added.
* editing/selection/doubleclick-inline-first-last-contenteditable.html: Added.
* editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js: Added.
2010-05-27 MORITA Hajime <morrita at google.com>
Reviewed by Ojan Vafai.
<http://webkit.org/b/36359>
Double clicking page's last editable inline element causes assertion failure.
<http://webkit.org/b/36360>
Double clicking page's first editable inline element cannot select a word.
nextBoundary() and previousBoundary() assumed that editable
boundaries are on block-level elements, But it can appear on
inline-level elements. So we start boundary look-up from the given
node, instead of the containingBlock of the given node.
Also, added TextIteratorEndsAtEditingBoundary to
BackwardsCharacterIterator, otherwise, the VisiblePosition
returned by BackwardsCharacterIterator might cross an editing
boundary.
Test: editing/selection/doubleclick-inline-first-last-contenteditable.html
* dom/Position.cpp:
(WebCore::Position::parentEditingBoundary): Added.
* dom/Position.h:
* editing/TextIterator.cpp:
(WebCore::TextIterator::TextIterator):
(WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
(WebCore::SimplifiedBackwardsTextIterator::advance):
(WebCore::SimplifiedBackwardsTextIterator::crossesEditingBoundary): Added.
(WebCore::SimplifiedBackwardsTextIterator::setCurrentNode): Added.
(WebCore::SimplifiedBackwardsTextIterator::clearCurrentNode): Added.
(WebCore::BackwardsCharacterIterator::BackwardsCharacterIterator):
* editing/TextIterator.h:
(WebCore::):
* editing/visible_units.cpp:
(WebCore::previousBoundary):
(WebCore::nextBoundary):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@64974 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index aee39e9..33c5329 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2010-05-20 MORITA Hajime <morrita at google.com>
+
+ Reviewed by Ojan Vafai.
+
+ <http://webkit.org/b/36360>
+ Double clicking page's first editable inline element cannot select a word.
+ <http://webkit.org/b/36359>
+ Double clicking page's last editable inline element causes assertion failure.
+
+ * editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt: Added.
+ * editing/selection/doubleclick-inline-first-last-contenteditable.html: Added.
+ * editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js: Added.
+
2010-08-09 Ilya Tikhonovsky <loislo at chromium.org>
Reviewed by Yury Semikhatsky.
diff --git a/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt
new file mode 100644
index 0000000..230e1b2
--- /dev/null
+++ b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt
@@ -0,0 +1,21 @@
+Test to check if last and first word can be selected when they double-clicked (Bug 36359)
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.getSelection().toString() is 'selectme1'
+PASS window.selectedByModify is 'selectme1'
+PASS window.getSelection().toString() is 'selectme2'
+PASS window.selectedByModify is 'selectme2'
+PASS window.getSelection().toString() is 'selectme3'
+PASS window.selectedByModify is 'selectme3'
+PASS window.getSelection().toString() is 'selectme4'
+PASS window.selectedByModify is 'selectme4'
+PASS window.getSelection().toString() is 'selectme5'
+PASS window.selectedByModify is 'selectme5'
+PASS window.getSelection().toString() is 'selectme6'
+PASS window.selectedByModify is 'selectme6'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable.html b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable.html
new file mode 100644
index 0000000..4d388c3
--- /dev/null
+++ b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="resources/js-test-selection-shared.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/doubleclick-inline-first-last-contenteditable.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js b/LayoutTests/editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js
new file mode 100644
index 0000000..eadc9c4
--- /dev/null
+++ b/LayoutTests/editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js
@@ -0,0 +1,108 @@
+description("Test to check if last and first word can be selected when they double-clicked (Bug 36359)");
+
+function toLiteral(textValue)
+{
+ return "'" + textValue + "'";
+}
+
+function getPositionOfNode(node)
+{
+ var n = node;
+ var offsetX = 0, offsetY = 0;
+
+ while (n) {
+ offsetX += n.offsetLeft;
+ offsetY += n.offsetTop;
+ n = n.offsetParnet;
+ }
+
+ return {
+ "x": offsetX,
+ "y": offsetY
+ };
+}
+
+function doubleClickPosition(pos)
+{
+ eventSender.mouseMoveTo(pos.x, pos.y);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+}
+
+function singleClickPosition(pos)
+{
+ eventSender.mouseMoveTo(pos.x, pos.y);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+}
+
+var targetRoot = document.createElement("div");
+document.body.appendChild(targetRoot);
+
+var scratchRoot = document.createElement("div");
+document.body.appendChild(scratchRoot);
+
+function computeTextSize(text)
+{
+ scratchRoot.innerHTML = ("<span id='scratch'>" + text + "</span>");
+ var scratch = document.getElementById("scratch");
+ return { width: scratch.offsetWidth, height: scratch.offsetHeight };
+}
+
+function testWithDoublleClick(targetInnerHTML, expectedText)
+{
+ var textSize = computeTextSize(expectedText);
+
+ targetRoot.innerHTML = targetInnerHTML;
+ var target = document.getElementById("target");
+ var nodePosition = getPositionOfNode(target);
+ doubleClickPosition({ x: nodePosition.x + textSize.width / 2, y: nodePosition.y + textSize.height / 2 });
+ shouldBe("window.getSelection().toString()", toLiteral(expectedText));
+}
+
+function testWithClickAndModify(targetInnerHTML, expectedText)
+{
+ var selection = window.getSelection();
+ targetRoot.innerHTML = targetInnerHTML;
+ var target = document.getElementById("target");
+ singleClickPosition(getPositionOfNode(target));
+
+ selection.modify("extend", "forward", "word");
+ var lastHalf = window.getSelection().toString();
+ selection.modify("extend", "backward", "word");
+ var firstHalf = window.getSelection().toString();
+
+ window.selectedByModify = firstHalf + lastHalf;
+ shouldBe("window.selectedByModify", toLiteral(expectedText));
+}
+
+var shouldSelecteFirstWordInline = "<span id='target' contentEditable>selectme1</span> and not select us";
+testWithDoublleClick(shouldSelecteFirstWordInline, "selectme1");
+testWithClickAndModify(shouldSelecteFirstWordInline, "selectme1");
+
+var shouldSelectLastWordInline = "you should ignore us but <span id='target' contentEditable>selectme2</span>";
+testWithDoublleClick(shouldSelectLastWordInline, "selectme2");
+testWithClickAndModify(shouldSelectLastWordInline, "selectme2");
+
+var shouldSelectMiddleWordInline = "you should get <span id='target' contentEditable>selectme3</span> selected";
+testWithDoublleClick(shouldSelectMiddleWordInline, "selectme3");
+testWithClickAndModify(shouldSelectMiddleWordInline, "selectme3");
+
+var shouldSelecteFirstWordBlock = "<div id='target' contentEditable>selectme4</div> and not select us";
+testWithDoublleClick(shouldSelecteFirstWordBlock, "selectme4");
+testWithClickAndModify(shouldSelecteFirstWordBlock, "selectme4");
+
+var shouldSelectLastWordBlock = "you should ignore us but <div id='target' contentEditable>selectme5</div>";
+testWithDoublleClick(shouldSelectLastWordBlock, "selectme5");
+testWithClickAndModify(shouldSelectLastWordBlock, "selectme5");
+
+var shouldSelectMiddleWordBlock = "you should get <div id='target' contentEditable>selectme6</div> selected";
+testWithDoublleClick(shouldSelectMiddleWordBlock, "selectme6");
+testWithClickAndModify(shouldSelectMiddleWordBlock, "selectme6");
+
+targetRoot.style.display = "none";
+scratchRoot.style.display = "none";
+
+var successfullyParsed = true;
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index ef2b2c9..f7c7ec7 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,40 @@
+2010-05-27 MORITA Hajime <morrita at google.com>
+
+ Reviewed by Ojan Vafai.
+
+ <http://webkit.org/b/36359>
+ Double clicking page's last editable inline element causes assertion failure.
+ <http://webkit.org/b/36360>
+ Double clicking page's first editable inline element cannot select a word.
+
+ nextBoundary() and previousBoundary() assumed that editable
+ boundaries are on block-level elements, But it can appear on
+ inline-level elements. So we start boundary look-up from the given
+ node, instead of the containingBlock of the given node.
+ Also, added TextIteratorEndsAtEditingBoundary to
+ BackwardsCharacterIterator, otherwise, the VisiblePosition
+ returned by BackwardsCharacterIterator might cross an editing
+ boundary.
+
+ Test: editing/selection/doubleclick-inline-first-last-contenteditable.html
+
+ * dom/Position.cpp:
+ (WebCore::Position::parentEditingBoundary): Added.
+ * dom/Position.h:
+ * editing/TextIterator.cpp:
+ (WebCore::TextIterator::TextIterator):
+ (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
+ (WebCore::SimplifiedBackwardsTextIterator::advance):
+ (WebCore::SimplifiedBackwardsTextIterator::crossesEditingBoundary): Added.
+ (WebCore::SimplifiedBackwardsTextIterator::setCurrentNode): Added.
+ (WebCore::SimplifiedBackwardsTextIterator::clearCurrentNode): Added.
+ (WebCore::BackwardsCharacterIterator::BackwardsCharacterIterator):
+ * editing/TextIterator.h:
+ (WebCore::):
+ * editing/visible_units.cpp:
+ (WebCore::previousBoundary):
+ (WebCore::nextBoundary):
+
2010-08-09 Ilya Tikhonovsky <loislo at chromium.org>
Reviewed by Yury Semikhatsky.
diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp
index 65b7261..4758bd9 100644
--- a/WebCore/dom/Position.cpp
+++ b/WebCore/dom/Position.cpp
@@ -328,6 +328,23 @@ bool Position::atEditingBoundary() const
&& prevPosition.isNotNull() && !prevPosition.node()->isContentEditable();
}
+Node* Position::parentEditingBoundary() const
+{
+ if (!m_anchorNode || !m_anchorNode->document())
+ return 0;
+
+ Node* documentElement = m_anchorNode->document()->documentElement();
+ if (!documentElement)
+ return 0;
+
+ Node* boundary = m_anchorNode.get();
+ while (boundary != documentElement && boundary->parentNode() && m_anchorNode->isContentEditable() == boundary->parentNode()->isContentEditable())
+ boundary = boundary->parentNode();
+
+ return boundary;
+}
+
+
bool Position::atStartOfTree() const
{
if (isNull())
diff --git a/WebCore/dom/Position.h b/WebCore/dom/Position.h
index f606c29..9f2ee24 100644
--- a/WebCore/dom/Position.h
+++ b/WebCore/dom/Position.h
@@ -138,6 +138,7 @@ public:
// Returns true if the visually equivalent positions around have different editability
bool atEditingBoundary() const;
+ Node* parentEditingBoundary() const;
bool atStartOfTree() const;
bool atEndOfTree() const;
diff --git a/WebCore/editing/TextIterator.cpp b/WebCore/editing/TextIterator.cpp
index f3bd9df..4d6c14a 100644
--- a/WebCore/editing/TextIterator.cpp
+++ b/WebCore/editing/TextIterator.cpp
@@ -272,6 +272,9 @@ TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior)
, m_entersTextControls(behavior & TextIteratorEntersTextControls)
, m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding)
{
+ // FIXME: should support TextIteratorEndsAtEditingBoundary http://webkit.org/b/43609
+ ASSERT(behavior != TextIteratorEndsAtEditingBoundary);
+
if (!r)
return;
@@ -944,13 +947,19 @@ Node* TextIterator::node() const
// --------
SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator()
- : m_positionNode(0)
+ : m_behavior(TextIteratorDefaultBehavior)
+ , m_node(0)
+ , m_positionNode(0)
{
}
-SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r)
- : m_positionNode(0)
+SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior)
+ : m_behavior(behavior)
+ , m_node(0)
+ , m_positionNode(0)
{
+ ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsAtEditingBoundary);
+
if (!r)
return;
@@ -974,7 +983,7 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r)
}
}
- m_node = endNode;
+ setCurrentNode(endNode);
setUpFullyClippedStack(m_fullyClippedStack, m_node);
m_offset = endOffset;
m_handledNode = false;
@@ -1038,12 +1047,9 @@ void SimplifiedBackwardsTextIterator::advance()
}
}
// Exit all other containers.
- next = m_node->previousSibling();
- while (!next) {
- Node* parentNode = parentCrossingShadowBoundaries(m_node);
- if (!parentNode)
+ while (!m_node->previousSibling()) {
+ if (!setCurrentNode(parentCrossingShadowBoundaries(m_node)))
break;
- m_node = parentNode;
m_fullyClippedStack.pop();
exitNode();
if (m_positionNode) {
@@ -1051,14 +1057,17 @@ void SimplifiedBackwardsTextIterator::advance()
m_handledChildren = true;
return;
}
- next = m_node->previousSibling();
}
+
+ next = m_node->previousSibling();
m_fullyClippedStack.pop();
}
- m_node = next;
- if (m_node)
+ if (m_node && setCurrentNode(next))
pushFullyClippedState(m_fullyClippedStack, m_node);
+ else
+ clearCurrentNode();
+
// For the purpose of word boundary detection,
// we should iterate all visible text and trailing (collapsed) whitespaces.
m_offset = m_node ? maxOffsetIncludingCollapsedSpaces(m_node) : 0;
@@ -1137,6 +1146,26 @@ void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta
m_lastCharacter = c;
}
+bool SimplifiedBackwardsTextIterator::crossesEditingBoundary(Node* node) const
+{
+ return m_node && m_node->isContentEditable() != node->isContentEditable();
+}
+
+bool SimplifiedBackwardsTextIterator::setCurrentNode(Node* node)
+{
+ if (!node)
+ return false;
+ if (m_behavior == TextIteratorEndsAtEditingBoundary && crossesEditingBoundary(node))
+ return false;
+ m_node = node;
+ return true;
+}
+
+void SimplifiedBackwardsTextIterator::clearCurrentNode()
+{
+ m_node = 0;
+}
+
PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const
{
if (m_positionNode)
@@ -1262,11 +1291,11 @@ BackwardsCharacterIterator::BackwardsCharacterIterator()
{
}
-BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range)
+BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehavior behavior)
: m_offset(0)
, m_runOffset(0)
, m_atBreak(true)
- , m_textIterator(range)
+ , m_textIterator(range, behavior)
{
while (!atEnd() && !m_textIterator.length())
m_textIterator.advance();
diff --git a/WebCore/editing/TextIterator.h b/WebCore/editing/TextIterator.h
index ba381b9..6a0d685 100644
--- a/WebCore/editing/TextIterator.h
+++ b/WebCore/editing/TextIterator.h
@@ -73,6 +73,7 @@ enum TextIteratorBehavior {
TextIteratorEmitsCharactersBetweenAllVisiblePositions = 1 << 0,
TextIteratorEntersTextControls = 1 << 1,
TextIteratorEmitsTextsWithoutTranscoding = 1 << 2,
+ TextIteratorEndsAtEditingBoundary = 1 << 3
};
class TextIterator {
@@ -167,7 +168,7 @@ private:
class SimplifiedBackwardsTextIterator {
public:
SimplifiedBackwardsTextIterator();
- explicit SimplifiedBackwardsTextIterator(const Range*);
+ explicit SimplifiedBackwardsTextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
bool atEnd() const { return !m_positionNode; }
void advance();
@@ -183,7 +184,11 @@ private:
bool handleReplacedElement();
bool handleNonTextNode();
void emitCharacter(UChar, Node*, int startOffset, int endOffset);
-
+ bool crossesEditingBoundary(Node*) const;
+ bool setCurrentNode(Node*);
+ void clearCurrentNode();
+
+ TextIteratorBehavior m_behavior;
// Current position, not necessarily of the text being returned, but position
// as we walk through the DOM tree.
Node* m_node;
@@ -247,7 +252,7 @@ private:
class BackwardsCharacterIterator {
public:
BackwardsCharacterIterator();
- explicit BackwardsCharacterIterator(const Range*);
+ explicit BackwardsCharacterIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
void advance(int);
@@ -256,6 +261,7 @@ public:
PassRefPtr<Range> range() const;
private:
+ TextIteratorBehavior m_behavior;
int m_offset;
int m_runOffset;
bool m_atBreak;
diff --git a/WebCore/editing/visible_units.cpp b/WebCore/editing/visible_units.cpp
index dd48406..4fce2d9 100644
--- a/WebCore/editing/visible_units.cpp
+++ b/WebCore/editing/visible_units.cpp
@@ -75,20 +75,11 @@ typedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsign
static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
{
Position pos = c.deepEquivalent();
- Node *n = pos.node();
- if (!n)
- return VisiblePosition();
- Document *d = n->document();
- Node *de = d->documentElement();
- if (!de)
- return VisiblePosition();
- Node *boundary = n->enclosingBlockFlowElement();
+ Node* boundary = pos.parentEditingBoundary();
if (!boundary)
return VisiblePosition();
- bool isContentEditable = boundary->isContentEditable();
- while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
- boundary = boundary->parentNode();
+ Document* d = boundary->document();
Position start = rangeCompliantEquivalent(Position(boundary, 0));
Position end = rangeCompliantEquivalent(pos);
RefPtr<Range> searchRange = Range::create(d);
@@ -121,7 +112,7 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
if (ec)
return VisiblePosition();
- SimplifiedBackwardsTextIterator it(searchRange.get());
+ SimplifiedBackwardsTextIterator it(searchRange.get(), TextIteratorEndsAtEditingBoundary);
unsigned next = 0;
bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;
bool needMoreContext = false;
@@ -156,7 +147,7 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
pos = Position(node, next);
else {
// Use the character iterator to translate the next value into a DOM position.
- BackwardsCharacterIterator charIt(searchRange.get());
+ BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsAtEditingBoundary);
charIt.advance(string.size() - suffixLength - next);
pos = charIt.range()->endPosition();
}
@@ -168,20 +159,11 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
{
Position pos = c.deepEquivalent();
- Node *n = pos.node();
- if (!n)
- return VisiblePosition();
- Document *d = n->document();
- Node *de = d->documentElement();
- if (!de)
- return VisiblePosition();
- Node *boundary = n->enclosingBlockFlowElement();
+ Node* boundary = pos.parentEditingBoundary();
if (!boundary)
return VisiblePosition();
- bool isContentEditable = boundary->isContentEditable();
- while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
- boundary = boundary->parentNode();
+ Document* d = boundary->document();
RefPtr<Range> searchRange(d->createRange());
Position start(rangeCompliantEquivalent(pos));
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list