<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[195949] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/195949">195949</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-01-31 20:09:02 -0800 (Sun, 31 Jan 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>AX: Add a boundary value to AXTextStateChangeType
https://bugs.webkit.org/show_bug.cgi?id=153085
Patch by Doug Russell <d_russell@apple.com> on 2016-01-31
Reviewed by Darin Adler.
Post an AT notification when navigation is attempted past
an editable element's boundaries.
Source/WebCore:
Test: accessibility/mac/selection-boundary-userinfo.html
* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::showIntent):
* accessibility/AXTextStateChangeIntent.h:
* accessibility/mac/AXObjectCacheMac.mm:
(platformChangeTypeForWebCoreChangeType):
(WebCore::AXObjectCache::postTextStateChangePlatformNotification):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::modifyMovingRight):
(WebCore::FrameSelection::modifyMovingForward):
(WebCore::FrameSelection::modifyMovingLeft):
(WebCore::FrameSelection::modifyMovingBackward):
(WebCore::textSelectionWithDirectionAndGranularity):
(WebCore::FrameSelection::modify):
(WebCore::FrameSelection::modifyExtendingBackward): Deleted.
(WebCore::FrameSelection::textSelectionIntent): Deleted.
* editing/FrameSelection.h:
* editing/VisiblePosition.cpp:
(WebCore::VisiblePosition::next):
(WebCore::VisiblePosition::previous):
(WebCore::VisiblePosition::left):
(WebCore::VisiblePosition::right):
(WebCore::VisiblePosition::honorEditingBoundaryAtOrBefore):
(WebCore::VisiblePosition::honorEditingBoundaryAtOrAfter):
(WebCore::VisiblePosition::leftVisuallyDistinctCandidate): Deleted.
(WebCore::VisiblePosition::rightVisuallyDistinctCandidate): Deleted.
* editing/VisiblePosition.h:
* editing/VisibleUnits.cpp:
(WebCore::startOfLine):
(WebCore::logicalStartOfLine):
(WebCore::endOfLine):
(WebCore::logicalEndOfLine):
(WebCore::leftBoundaryOfLine):
(WebCore::rightBoundaryOfLine):
(WebCore::inSameLogicalLine): Deleted.
(WebCore::endOfEditableContent): Deleted.
(WebCore::isEndOfEditableOrNonEditableContent): Deleted.
* editing/VisibleUnits.h:
LayoutTests:
* accessibility/mac/selection-boundary-userinfo-expected.txt: Added.
* accessibility/mac/selection-boundary-userinfo.html: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXObjectCachecpp">trunk/Source/WebCore/accessibility/AXObjectCache.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXTextStateChangeIntenth">trunk/Source/WebCore/accessibility/AXTextStateChangeIntent.h</a></li>
<li><a href="#trunkSourceWebCoreaccessibilitymacAXObjectCacheMacmm">trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm</a></li>
<li><a href="#trunkSourceWebCoreeditingFrameSelectioncpp">trunk/Source/WebCore/editing/FrameSelection.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingFrameSelectionh">trunk/Source/WebCore/editing/FrameSelection.h</a></li>
<li><a href="#trunkSourceWebCoreeditingVisiblePositioncpp">trunk/Source/WebCore/editing/VisiblePosition.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingVisiblePositionh">trunk/Source/WebCore/editing/VisiblePosition.h</a></li>
<li><a href="#trunkSourceWebCoreeditingVisibleUnitscpp">trunk/Source/WebCore/editing/VisibleUnits.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingVisibleUnitsh">trunk/Source/WebCore/editing/VisibleUnits.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilitymacselectionboundaryuserinfoexpectedtxt">trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymacselectionboundaryuserinfohtml">trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/LayoutTests/ChangeLog        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-01-31 Doug Russell <d_russell@apple.com>
+
+ AX: Add a boundary value to AXTextStateChangeType
+ https://bugs.webkit.org/show_bug.cgi?id=153085
+
+ Reviewed by Darin Adler.
+
+ Post an AT notification when navigation is attempted past
+ an editable element's boundaries.
+
+ * accessibility/mac/selection-boundary-userinfo-expected.txt: Added.
+ * accessibility/mac/selection-boundary-userinfo.html: Added.
+
</ins><span class="cx"> 2016-01-31 Daniel Bates <dabates@apple.com>
</span><span class="cx">
</span><span class="cx"> CSP: Use the served CSP header for dedicated workers
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymacselectionboundaryuserinfoexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo-expected.txt (0 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo-expected.txt         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo-expected.txt        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+This tests selection change notifications at text boundaries.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS addedNotification is true
+PASS results[i] is AXTextStateChangeTypeSelectionMove
+PASS results[i] is AXTextSelectionDirectionDiscontiguous
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityCharacter
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityCharacter
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityWord
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityWord
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionBeginning
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionEnd
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityDocument
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityDocument
+PASS results[i] is AXTextStateChangeTypeSelectionMove
+PASS results[i] is AXTextSelectionDirectionDiscontiguous
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityCharacter
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityCharacter
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityWord
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityWord
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionBeginning
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionEnd
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionMove
+PASS results[i] is AXTextSelectionDirectionDiscontiguous
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityCharacter
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityCharacter
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityWord
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityWord
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionBeginning
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionEnd
+PASS results[i] is AXTextSelectionGranularityLine
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionPrevious
+PASS results[i] is AXTextSelectionGranularityDocument
+PASS results[i] is AXTextStateChangeTypeSelectionBoundary
+PASS results[i] is AXTextSelectionDirectionNext
+PASS results[i] is AXTextSelectionGranularityDocument
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymacselectionboundaryuserinfohtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo.html (0 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo.html         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo.html        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -0,0 +1,185 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body id="body">
+
+<div role="textbox" tabindex=0 id="textbox" contenteditable=true>
+ <p><br>
+</div>
+
+<br>
+
+<input type="text" id="input">
+
+<br>
+
+<textarea id="textarea"></textarea>
+
+<script>
+
+ description("This tests selection change notifications at text boundaries.");
+
+ var AXTextStateChangeTypeSelectionMove = 2;
+ var AXTextStateChangeTypeSelectionExtend = AXTextStateChangeTypeSelectionMove + 1;
+ var AXTextStateChangeTypeSelectionBoundary = AXTextStateChangeTypeSelectionExtend + 1;
+
+ var AXTextSelectionDirectionBeginning = 1;
+ var AXTextSelectionDirectionEnd = AXTextSelectionDirectionBeginning + 1;
+ var AXTextSelectionDirectionPrevious = AXTextSelectionDirectionEnd + 1;
+ var AXTextSelectionDirectionNext = AXTextSelectionDirectionPrevious + 1;
+ var AXTextSelectionDirectionDiscontiguous = AXTextSelectionDirectionNext + 1;
+
+ var AXTextSelectionGranularityCharacter = 1;
+ var AXTextSelectionGranularityWord = AXTextSelectionGranularityCharacter + 1;
+ var AXTextSelectionGranularityLine = AXTextSelectionGranularityWord + 1;
+ var AXTextSelectionGranularitySentence = AXTextSelectionGranularityLine + 1;
+ var AXTextSelectionGranularityParagraph = AXTextSelectionGranularitySentence + 1;
+ var AXTextSelectionGranularityDocument = AXTextSelectionGranularityParagraph + 2;
+
+ function move(includeVertical) {
+ // Move by character
+ eventSender.keyDown("leftArrow");
+ eventSender.keyDown("rightArrow");
+ if (includeVertical) {
+ // Move by line
+ eventSender.keyDown("upArrow");
+ eventSender.keyDown("downArrow");
+ }
+ // Move by word
+ eventSender.keyDown("leftArrow", ["altKey"]);
+ eventSender.keyDown("rightArrow", ["altKey"]);
+ // Move to beginning/end of line
+ eventSender.keyDown("leftArrow", ["metaKey"]);
+ eventSender.keyDown("rightArrow", ["metaKey"]);
+ if (includeVertical) {
+ // Move to beginning/end of document
+ eventSender.keyDown("upArrow", ["metaKey"]);
+ eventSender.keyDown("downArrow", ["metaKey"]);
+ }
+ }
+
+ var webArea = 0;
+ var count = 0;
+ var results = [];
+ var i = 0;
+ function notificationCallback(notification, userInfo) {
+ if (notification == "AXSelectedTextChanged") {
+ count++;
+ if (userInfo) {
+ results.push(userInfo["AXTextStateChangeType"]);
+ if (userInfo["AXTextSelectionDirection"])
+ results.push(userInfo["AXTextSelectionDirection"]);
+ if (userInfo["AXTextSelectionGranularity"])
+ results.push(userInfo["AXTextSelectionGranularity"]);
+ }
+ if (count == 29) {
+
+ function shouldBeResults(includeVertical) {
+ // Focusing into the textbox
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionMove"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionDiscontiguous"); i++;
+
+ // Left Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionPrevious"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityCharacter"); i++;
+
+ // Right Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionNext"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityCharacter"); i++;
+
+ if (includeVertical) {
+ // Up Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionPrevious"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityLine"); i++;
+
+ // Down Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionNext"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityLine"); i++;
+ }
+
+ // Option Left Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionPrevious"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityWord"); i++;
+
+ // Option Right Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionNext"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityWord"); i++;
+
+ // Command Left Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionBeginning"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityLine"); i++;
+
+ // Command Right Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ shouldBe("results[i]", "AXTextSelectionDirectionEnd"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityLine"); i++;
+
+ if (includeVertical) {
+ // Command Up Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ // FIXME: This should be AXTextSelectionDirectionBeginning.
+ shouldBe("results[i]", "AXTextSelectionDirectionPrevious"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityDocument"); i++;
+
+ // Command Down Arrow
+ shouldBe("results[i]", "AXTextStateChangeTypeSelectionBoundary"); i++;
+ // FIXME: This should be AXTextSelectionDirectionEnd.
+ shouldBe("results[i]", "AXTextSelectionDirectionNext"); i++;
+ shouldBe("results[i]", "AXTextSelectionGranularityDocument"); i++;
+ }
+ }
+
+ // Content Editable Div
+ shouldBeResults(true);
+
+ // Text Field
+ shouldBeResults(false);
+
+ // Text Area
+ shouldBeResults(true);
+
+ webArea.removeNotificationListener();
+ window.testRunner.notifyDone();
+ }
+ }
+ }
+
+ if (window.accessibilityController) {
+ window.testRunner.waitUntilDone();
+
+ accessibilityController.enableEnhancedAccessibility(true);
+
+ webArea = accessibilityController.rootElement.childAtIndex(0);
+ var addedNotification = webArea.addNotificationListener(notificationCallback);
+ shouldBe("addedNotification", "true");
+
+ textbox = document.getElementById("textbox");
+ textbox.focus();
+
+ move(true);
+
+ textbox = document.getElementById("input");
+ textbox.focus();
+
+ move(false);
+
+ textbox = document.getElementById("textarea");
+ textbox.focus();
+
+ move(true);
+ }
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/ChangeLog        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -1,3 +1,53 @@
</span><ins>+2016-01-31 Doug Russell <d_russell@apple.com>
+
+ AX: Add a boundary value to AXTextStateChangeType
+ https://bugs.webkit.org/show_bug.cgi?id=153085
+
+ Reviewed by Darin Adler.
+
+ Post an AT notification when navigation is attempted past
+ an editable element's boundaries.
+
+ Test: accessibility/mac/selection-boundary-userinfo.html
+
+ * accessibility/AXObjectCache.cpp:
+ (WebCore::AXObjectCache::showIntent):
+ * accessibility/AXTextStateChangeIntent.h:
+ * accessibility/mac/AXObjectCacheMac.mm:
+ (platformChangeTypeForWebCoreChangeType):
+ (WebCore::AXObjectCache::postTextStateChangePlatformNotification):
+ * editing/FrameSelection.cpp:
+ (WebCore::FrameSelection::modifyMovingRight):
+ (WebCore::FrameSelection::modifyMovingForward):
+ (WebCore::FrameSelection::modifyMovingLeft):
+ (WebCore::FrameSelection::modifyMovingBackward):
+ (WebCore::textSelectionWithDirectionAndGranularity):
+ (WebCore::FrameSelection::modify):
+ (WebCore::FrameSelection::modifyExtendingBackward): Deleted.
+ (WebCore::FrameSelection::textSelectionIntent): Deleted.
+ * editing/FrameSelection.h:
+ * editing/VisiblePosition.cpp:
+ (WebCore::VisiblePosition::next):
+ (WebCore::VisiblePosition::previous):
+ (WebCore::VisiblePosition::left):
+ (WebCore::VisiblePosition::right):
+ (WebCore::VisiblePosition::honorEditingBoundaryAtOrBefore):
+ (WebCore::VisiblePosition::honorEditingBoundaryAtOrAfter):
+ (WebCore::VisiblePosition::leftVisuallyDistinctCandidate): Deleted.
+ (WebCore::VisiblePosition::rightVisuallyDistinctCandidate): Deleted.
+ * editing/VisiblePosition.h:
+ * editing/VisibleUnits.cpp:
+ (WebCore::startOfLine):
+ (WebCore::logicalStartOfLine):
+ (WebCore::endOfLine):
+ (WebCore::logicalEndOfLine):
+ (WebCore::leftBoundaryOfLine):
+ (WebCore::rightBoundaryOfLine):
+ (WebCore::inSameLogicalLine): Deleted.
+ (WebCore::endOfEditableContent): Deleted.
+ (WebCore::isEndOfEditableOrNonEditableContent): Deleted.
+ * editing/VisibleUnits.h:
+
</ins><span class="cx"> 2016-01-31 Daniel Bates <dabates@apple.com>
</span><span class="cx">
</span><span class="cx"> CSP: Use the served CSP header for dedicated workers
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -995,6 +995,9 @@
</span><span class="cx"> case AXTextStateChangeTypeSelectionExtend:
</span><span class="cx"> dataLog("Extend::");
</span><span class="cx"> break;
</span><ins>+ case AXTextStateChangeTypeSelectionBoundary:
+ dataLog("Boundary::");
+ break;
</ins><span class="cx"> }
</span><span class="cx"> switch (intent.type) {
</span><span class="cx"> case AXTextStateChangeTypeUnknown:
</span><span class="lines">@@ -1029,6 +1032,7 @@
</span><span class="cx"> break;
</span><span class="cx"> case AXTextStateChangeTypeSelectionMove:
</span><span class="cx"> case AXTextStateChangeTypeSelectionExtend:
</span><ins>+ case AXTextStateChangeTypeSelectionBoundary:
</ins><span class="cx"> switch (intent.selection.direction) {
</span><span class="cx"> case AXTextSelectionDirectionUnknown:
</span><span class="cx"> dataLog("Unknown::");
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXTextStateChangeIntenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXTextStateChangeIntent.h (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXTextStateChangeIntent.h        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/accessibility/AXTextStateChangeIntent.h        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -32,7 +32,8 @@
</span><span class="cx"> AXTextStateChangeTypeUnknown,
</span><span class="cx"> AXTextStateChangeTypeEdit,
</span><span class="cx"> AXTextStateChangeTypeSelectionMove,
</span><del>- AXTextStateChangeTypeSelectionExtend
</del><ins>+ AXTextStateChangeTypeSelectionExtend,
+ AXTextStateChangeTypeSelectionBoundary
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> enum AXTextEditType {
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilitymacAXObjectCacheMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -158,6 +158,8 @@
</span><span class="cx"> return kAXTextStateChangeTypeSelectionMove;
</span><span class="cx"> case WebCore::AXTextStateChangeTypeSelectionExtend:
</span><span class="cx"> return kAXTextStateChangeTypeSelectionExtend;
</span><ins>+ case WebCore::AXTextStateChangeTypeSelectionBoundary:
+ return kAXTextStateChangeTypeSelectionBoundary;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -365,6 +367,7 @@
</span><span class="cx"> switch (intent.type) {
</span><span class="cx"> case AXTextStateChangeTypeSelectionMove:
</span><span class="cx"> case AXTextStateChangeTypeSelectionExtend:
</span><ins>+ case AXTextStateChangeTypeSelectionBoundary:
</ins><span class="cx"> [userInfo setObject:@(platformDirectionForWebCoreDirection(intent.selection.direction)) forKey:NSAccessibilityTextSelectionDirection];
</span><span class="cx"> switch (intent.selection.direction) {
</span><span class="cx"> case AXTextSelectionDirectionUnknown:
</span><span class="lines">@@ -378,13 +381,13 @@
</span><span class="cx"> case AXTextSelectionDirectionDiscontiguous:
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ if (intent.selection.focusChange)
+ [userInfo setObject:@(intent.selection.focusChange) forKey:NSAccessibilityTextSelectionChangedFocus];
</ins><span class="cx"> break;
</span><span class="cx"> case AXTextStateChangeTypeUnknown:
</span><span class="cx"> case AXTextStateChangeTypeEdit:
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- if (intent.selection.focusChange)
- [userInfo setObject:[NSNumber numberWithBool:intent.selection.focusChange] forKey:NSAccessibilityTextSelectionChangedFocus];
</del><span class="cx"> }
</span><span class="cx"> if (!selection.isNone()) {
</span><span class="cx"> if (id textMarkerRange = [object->wrapper() textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()])
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingFrameSelectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/FrameSelection.cpp        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -760,8 +760,10 @@
</span><span class="cx"> return pos;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
</del><ins>+VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity, bool* reachedBoundary)
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> VisiblePosition pos;
</span><span class="cx"> switch (granularity) {
</span><span class="cx"> case CharacterGranularity:
</span><span class="lines">@@ -771,11 +773,14 @@
</span><span class="cx"> else
</span><span class="cx"> pos = VisiblePosition(m_selection.start(), m_selection.affinity());
</span><span class="cx"> } else
</span><del>- pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
</del><ins>+ pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true, reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case WordGranularity: {
</span><span class="cx"> bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
</span><del>- pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
</del><ins>+ VisiblePosition currentPosition(m_selection.extent(), m_selection.affinity());
+ pos = rightWordPosition(currentPosition, skipsSpaceWhenMovingRight);
+ if (reachedBoundary)
+ *reachedBoundary = pos == currentPosition;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case SentenceGranularity:
</span><span class="lines">@@ -785,10 +790,10 @@
</span><span class="cx"> case ParagraphBoundary:
</span><span class="cx"> case DocumentBoundary:
</span><span class="cx"> // FIXME: Implement all of the above.
</span><del>- pos = modifyMovingForward(granularity);
</del><ins>+ pos = modifyMovingForward(granularity, reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case LineBoundary:
</span><del>- pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
</del><ins>+ pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock(), reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case DocumentGranularity:
</span><span class="cx"> ASSERT_NOT_REACHED();
</span><span class="lines">@@ -797,8 +802,26 @@
</span><span class="cx"> return pos;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity)
</del><ins>+VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity, bool* reachedBoundary)
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
+ VisiblePosition currentPosition;
+ switch (granularity) {
+ case WordGranularity:
+ case SentenceGranularity:
+ currentPosition = VisiblePosition(m_selection.extent(), m_selection.affinity());
+ break;
+ case LineGranularity:
+ case ParagraphGranularity:
+ case SentenceBoundary:
+ case ParagraphBoundary:
+ case DocumentBoundary:
+ currentPosition = endForPlatform();
+ break;
+ default:
+ break;
+ }
</ins><span class="cx"> VisiblePosition pos;
</span><span class="cx"> // FIXME: Stay in editable content for the less common granularities.
</span><span class="cx"> switch (granularity) {
</span><span class="lines">@@ -806,45 +829,59 @@
</span><span class="cx"> if (isRange())
</span><span class="cx"> pos = VisiblePosition(m_selection.end(), m_selection.affinity());
</span><span class="cx"> else
</span><del>- pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CannotCrossEditingBoundary);
</del><ins>+ pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CannotCrossEditingBoundary, reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case WordGranularity:
</span><del>- pos = nextWordPositionForPlatform(VisiblePosition(m_selection.extent(), m_selection.affinity()));
</del><ins>+ pos = nextWordPositionForPlatform(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case SentenceGranularity:
</span><del>- pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
</del><ins>+ pos = nextSentencePosition(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case LineGranularity: {
</span><span class="cx"> // down-arrowing from a range selection that ends at the start of a line needs
</span><span class="cx"> // to leave the selection at that line start (no need to call nextLinePosition!)
</span><del>- pos = endForPlatform();
</del><ins>+ pos = currentPosition;
</ins><span class="cx"> if (!isRange() || !isStartOfLine(pos))
</span><span class="cx"> pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(START));
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case ParagraphGranularity:
</span><del>- pos = nextParagraphPosition(endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
</del><ins>+ pos = nextParagraphPosition(currentPosition, lineDirectionPointForBlockDirectionNavigation(START));
</ins><span class="cx"> break;
</span><span class="cx"> case DocumentGranularity:
</span><span class="cx"> ASSERT_NOT_REACHED();
</span><span class="cx"> break;
</span><span class="cx"> case SentenceBoundary:
</span><del>- pos = endOfSentence(endForPlatform());
</del><ins>+ pos = endOfSentence(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case LineBoundary:
</span><del>- pos = logicalEndOfLine(endForPlatform());
</del><ins>+ pos = logicalEndOfLine(endForPlatform(), reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case ParagraphBoundary:
</span><del>- pos = endOfParagraph(endForPlatform());
</del><ins>+ pos = endOfParagraph(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case DocumentBoundary:
</span><del>- pos = endForPlatform();
</del><ins>+ pos = currentPosition;
</ins><span class="cx"> if (isEditablePosition(pos.deepEquivalent()))
</span><span class="cx"> pos = endOfEditableContent(pos);
</span><span class="cx"> else
</span><span class="cx"> pos = endOfDocument(pos);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ switch (granularity) {
+ case WordGranularity:
+ case SentenceGranularity:
+ case LineGranularity:
+ case ParagraphGranularity:
+ case SentenceBoundary:
+ case ParagraphBoundary:
+ case DocumentBoundary:
+ if (reachedBoundary)
+ *reachedBoundary = pos == currentPosition;
+ break;
+ default:
+ break;
+ }
</ins><span class="cx"> return pos;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -944,8 +981,10 @@
</span><span class="cx"> return pos;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
</del><ins>+VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity, bool* reachedBoundary)
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> VisiblePosition pos;
</span><span class="cx"> switch (granularity) {
</span><span class="cx"> case CharacterGranularity:
</span><span class="lines">@@ -955,11 +994,14 @@
</span><span class="cx"> else
</span><span class="cx"> pos = VisiblePosition(m_selection.end(), m_selection.affinity());
</span><span class="cx"> else
</span><del>- pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
</del><ins>+ pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true, reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case WordGranularity: {
</span><span class="cx"> bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
</span><del>- pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
</del><ins>+ VisiblePosition currentPosition(m_selection.extent(), m_selection.affinity());
+ pos = leftWordPosition(currentPosition, skipsSpaceWhenMovingRight);
+ if (reachedBoundary)
+ *reachedBoundary = pos == currentPosition;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case SentenceGranularity:
</span><span class="lines">@@ -969,10 +1011,10 @@
</span><span class="cx"> case ParagraphBoundary:
</span><span class="cx"> case DocumentBoundary:
</span><span class="cx"> // FIXME: Implement all of the above.
</span><del>- pos = modifyMovingBackward(granularity);
</del><ins>+ pos = modifyMovingBackward(granularity, reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case LineBoundary:
</span><del>- pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
</del><ins>+ pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock(), reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case DocumentGranularity:
</span><span class="cx"> ASSERT_NOT_REACHED();
</span><span class="lines">@@ -981,39 +1023,57 @@
</span><span class="cx"> return pos;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity)
</del><ins>+VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity, bool* reachedBoundary)
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
+ VisiblePosition currentPosition;
+ switch (granularity) {
+ case WordGranularity:
+ case SentenceGranularity:
+ currentPosition = VisiblePosition(m_selection.extent(), m_selection.affinity());
+ break;
+ case LineGranularity:
+ case ParagraphGranularity:
+ case SentenceBoundary:
+ case ParagraphBoundary:
+ case DocumentBoundary:
+ currentPosition = startForPlatform();
+ break;
+ default:
+ break;
+ }
</ins><span class="cx"> VisiblePosition pos;
</span><span class="cx"> switch (granularity) {
</span><span class="cx"> case CharacterGranularity:
</span><span class="cx"> if (isRange())
</span><span class="cx"> pos = VisiblePosition(m_selection.start(), m_selection.affinity());
</span><span class="cx"> else
</span><del>- pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CannotCrossEditingBoundary);
</del><ins>+ pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CannotCrossEditingBoundary, reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case WordGranularity:
</span><del>- pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
</del><ins>+ pos = previousWordPosition(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case SentenceGranularity:
</span><del>- pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
</del><ins>+ pos = previousSentencePosition(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case LineGranularity:
</span><del>- pos = previousLinePosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
</del><ins>+ pos = previousLinePosition(currentPosition, lineDirectionPointForBlockDirectionNavigation(START));
</ins><span class="cx"> break;
</span><span class="cx"> case ParagraphGranularity:
</span><del>- pos = previousParagraphPosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
</del><ins>+ pos = previousParagraphPosition(currentPosition, lineDirectionPointForBlockDirectionNavigation(START));
</ins><span class="cx"> break;
</span><span class="cx"> case SentenceBoundary:
</span><del>- pos = startOfSentence(startForPlatform());
</del><ins>+ pos = startOfSentence(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case LineBoundary:
</span><del>- pos = logicalStartOfLine(startForPlatform());
</del><ins>+ pos = logicalStartOfLine(startForPlatform(), reachedBoundary);
</ins><span class="cx"> break;
</span><span class="cx"> case ParagraphBoundary:
</span><del>- pos = startOfParagraph(startForPlatform());
</del><ins>+ pos = startOfParagraph(currentPosition);
</ins><span class="cx"> break;
</span><span class="cx"> case DocumentBoundary:
</span><del>- pos = startForPlatform();
</del><ins>+ pos = currentPosition;
</ins><span class="cx"> if (isEditablePosition(pos.deepEquivalent()))
</span><span class="cx"> pos = startOfEditableContent(pos);
</span><span class="cx"> else
</span><span class="lines">@@ -1023,6 +1083,20 @@
</span><span class="cx"> ASSERT_NOT_REACHED();
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ switch (granularity) {
+ case WordGranularity:
+ case SentenceGranularity:
+ case LineGranularity:
+ case ParagraphGranularity:
+ case SentenceBoundary:
+ case ParagraphBoundary:
+ case DocumentBoundary:
+ if (reachedBoundary)
+ *reachedBoundary = pos == currentPosition;
+ break;
+ default:
+ break;
+ }
</ins><span class="cx"> return pos;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1099,6 +1173,68 @@
</span><span class="cx"> return intent;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static AXTextSelection textSelectionWithDirectionAndGranularity(SelectionDirection direction, TextGranularity granularity)
+{
+ // FIXME: Account for BIDI in DirectionRight & DirectionLeft. (In a RTL block, Right would map to Previous/Beginning and Left to Next/End.)
+ AXTextSelectionDirection intentDirection = AXTextSelectionDirectionUnknown;
+ switch (direction) {
+ case DirectionForward:
+ intentDirection = AXTextSelectionDirectionNext;
+ break;
+ case DirectionRight:
+ intentDirection = AXTextSelectionDirectionNext;
+ break;
+ case DirectionBackward:
+ intentDirection = AXTextSelectionDirectionPrevious;
+ break;
+ case DirectionLeft:
+ intentDirection = AXTextSelectionDirectionPrevious;
+ break;
+ }
+ AXTextSelectionGranularity intentGranularity = AXTextSelectionGranularityUnknown;
+ switch (granularity) {
+ case CharacterGranularity:
+ intentGranularity = AXTextSelectionGranularityCharacter;
+ break;
+ case WordGranularity:
+ intentGranularity = AXTextSelectionGranularityWord;
+ break;
+ case SentenceGranularity:
+ case SentenceBoundary: // FIXME: Boundary should affect direction.
+ intentGranularity = AXTextSelectionGranularitySentence;
+ break;
+ case LineGranularity:
+ intentGranularity = AXTextSelectionGranularityLine;
+ break;
+ case ParagraphGranularity:
+ case ParagraphBoundary: // FIXME: Boundary should affect direction.
+ intentGranularity = AXTextSelectionGranularityParagraph;
+ break;
+ case DocumentGranularity:
+ case DocumentBoundary: // FIXME: Boundary should affect direction.
+ intentGranularity = AXTextSelectionGranularityDocument;
+ break;
+ case LineBoundary:
+ intentGranularity = AXTextSelectionGranularityLine;
+ switch (direction) {
+ case DirectionForward:
+ intentDirection = AXTextSelectionDirectionEnd;
+ break;
+ case DirectionRight:
+ intentDirection = AXTextSelectionDirectionEnd;
+ break;
+ case DirectionBackward:
+ intentDirection = AXTextSelectionDirectionBeginning;
+ break;
+ case DirectionLeft:
+ intentDirection = AXTextSelectionDirectionBeginning;
+ break;
+ }
+ break;
+ }
+ return { intentDirection, intentGranularity, false };
+}
+
</ins><span class="cx"> bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered userTriggered)
</span><span class="cx"> {
</span><span class="cx"> if (userTriggered == UserTriggered) {
</span><span class="lines">@@ -1116,13 +1252,14 @@
</span><span class="cx">
</span><span class="cx"> willBeModified(alter, direction);
</span><span class="cx">
</span><ins>+ bool shouldNotify = false;
</ins><span class="cx"> bool wasRange = m_selection.isRange();
</span><span class="cx"> Position originalStartPosition = m_selection.start();
</span><span class="cx"> VisiblePosition position;
</span><span class="cx"> switch (direction) {
</span><span class="cx"> case DirectionRight:
</span><span class="cx"> if (alter == AlterationMove)
</span><del>- position = modifyMovingRight(granularity);
</del><ins>+ position = modifyMovingRight(granularity, &shouldNotify);
</ins><span class="cx"> else
</span><span class="cx"> position = modifyExtendingRight(granularity);
</span><span class="cx"> break;
</span><span class="lines">@@ -1130,11 +1267,11 @@
</span><span class="cx"> if (alter == AlterationExtend)
</span><span class="cx"> position = modifyExtendingForward(granularity);
</span><span class="cx"> else
</span><del>- position = modifyMovingForward(granularity);
</del><ins>+ position = modifyMovingForward(granularity, &shouldNotify);
</ins><span class="cx"> break;
</span><span class="cx"> case DirectionLeft:
</span><span class="cx"> if (alter == AlterationMove)
</span><del>- position = modifyMovingLeft(granularity);
</del><ins>+ position = modifyMovingLeft(granularity, &shouldNotify);
</ins><span class="cx"> else
</span><span class="cx"> position = modifyExtendingLeft(granularity);
</span><span class="cx"> break;
</span><span class="lines">@@ -1142,9 +1279,14 @@
</span><span class="cx"> if (alter == AlterationExtend)
</span><span class="cx"> position = modifyExtendingBackward(granularity);
</span><span class="cx"> else
</span><del>- position = modifyMovingBackward(granularity);
</del><ins>+ position = modifyMovingBackward(granularity, &shouldNotify);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+
+ if (shouldNotify && userTriggered == UserTriggered && m_frame && AXObjectCache::accessibilityEnabled()) {
+ notifyAccessibilityForSelectionChange({ AXTextStateChangeTypeSelectionBoundary, textSelectionWithDirectionAndGranularity(direction, granularity) });
+ return true;
+ }
</ins><span class="cx">
</span><span class="cx"> if (position.isNull())
</span><span class="cx"> return false;
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingFrameSelectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/FrameSelection.h (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/FrameSelection.h        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/editing/FrameSelection.h        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -291,12 +291,12 @@
</span><span class="cx">
</span><span class="cx"> VisiblePosition modifyExtendingRight(TextGranularity);
</span><span class="cx"> VisiblePosition modifyExtendingForward(TextGranularity);
</span><del>- VisiblePosition modifyMovingRight(TextGranularity);
- VisiblePosition modifyMovingForward(TextGranularity);
</del><ins>+ VisiblePosition modifyMovingRight(TextGranularity, bool* reachedBoundary = nullptr);
+ VisiblePosition modifyMovingForward(TextGranularity, bool* reachedBoundary = nullptr);
</ins><span class="cx"> VisiblePosition modifyExtendingLeft(TextGranularity);
</span><span class="cx"> VisiblePosition modifyExtendingBackward(TextGranularity);
</span><del>- VisiblePosition modifyMovingLeft(TextGranularity);
- VisiblePosition modifyMovingBackward(TextGranularity);
</del><ins>+ VisiblePosition modifyMovingLeft(TextGranularity, bool* reachedBoundary = nullptr);
+ VisiblePosition modifyMovingBackward(TextGranularity, bool* reachedBoundary = nullptr);
</ins><span class="cx">
</span><span class="cx"> LayoutUnit lineDirectionPointForBlockDirectionNavigation(EPositionType);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisiblePositioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisiblePosition.cpp (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisiblePosition.cpp        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/editing/VisiblePosition.cpp        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -63,8 +63,10 @@
</span><span class="cx"> m_affinity = DOWNSTREAM;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition VisiblePosition::next(EditingBoundaryCrossingRule rule) const
</del><ins>+VisiblePosition VisiblePosition::next(EditingBoundaryCrossingRule rule, bool* reachedBoundary) const
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> // FIXME: Support CanSkipEditingBoundary
</span><span class="cx"> ASSERT(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary);
</span><span class="cx"> VisiblePosition next(nextVisuallyDistinctCandidate(m_deepPosition), m_affinity);
</span><span class="lines">@@ -72,19 +74,24 @@
</span><span class="cx"> if (rule == CanCrossEditingBoundary)
</span><span class="cx"> return next;
</span><span class="cx">
</span><del>- return honorEditingBoundaryAtOrAfter(next);
</del><ins>+ return honorEditingBoundaryAtOrAfter(next, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition VisiblePosition::previous(EditingBoundaryCrossingRule rule) const
</del><ins>+VisiblePosition VisiblePosition::previous(EditingBoundaryCrossingRule rule, bool* reachedBoundary) const
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> // FIXME: Support CanSkipEditingBoundary
</span><span class="cx"> ASSERT(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary);
</span><span class="cx"> // find first previous DOM position that is visible
</span><span class="cx"> Position pos = previousVisuallyDistinctCandidate(m_deepPosition);
</span><span class="cx">
</span><span class="cx"> // return null visible position if there is no previous visible position
</span><del>- if (pos.atStartOfTree())
</del><ins>+ if (pos.atStartOfTree()) {
+ if (reachedBoundary)
+ *reachedBoundary = true;
</ins><span class="cx"> return VisiblePosition();
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> VisiblePosition prev = VisiblePosition(pos, DOWNSTREAM);
</span><span class="cx"> ASSERT(prev != *this);
</span><span class="lines">@@ -102,7 +109,7 @@
</span><span class="cx"> if (rule == CanCrossEditingBoundary)
</span><span class="cx"> return prev;
</span><span class="cx">
</span><del>- return honorEditingBoundaryAtOrBefore(prev);
</del><ins>+ return honorEditingBoundaryAtOrBefore(prev, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Position VisiblePosition::leftVisuallyDistinctCandidate() const
</span><span class="lines">@@ -253,12 +260,17 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition VisiblePosition::left(bool stayInEditableContent) const
</del><ins>+VisiblePosition VisiblePosition::left(bool stayInEditableContent, bool* reachedBoundary) const
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> Position pos = leftVisuallyDistinctCandidate();
</span><span class="cx"> // FIXME: Why can't we move left from the last position in a tree?
</span><del>- if (pos.atStartOfTree() || pos.atEndOfTree())
</del><ins>+ if (pos.atStartOfTree() || pos.atEndOfTree()) {
+ if (reachedBoundary)
+ *reachedBoundary = true;
</ins><span class="cx"> return VisiblePosition();
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> VisiblePosition left = VisiblePosition(pos, DOWNSTREAM);
</span><span class="cx"> ASSERT(left != *this);
</span><span class="lines">@@ -267,7 +279,7 @@
</span><span class="cx"> return left;
</span><span class="cx">
</span><span class="cx"> // FIXME: This may need to do something different from "before".
</span><del>- return honorEditingBoundaryAtOrBefore(left);
</del><ins>+ return honorEditingBoundaryAtOrBefore(left, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Position VisiblePosition::rightVisuallyDistinctCandidate() const
</span><span class="lines">@@ -421,12 +433,17 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition VisiblePosition::right(bool stayInEditableContent) const
</del><ins>+VisiblePosition VisiblePosition::right(bool stayInEditableContent, bool* reachedBoundary) const
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> Position pos = rightVisuallyDistinctCandidate();
</span><span class="cx"> // FIXME: Why can't we move left from the last position in a tree?
</span><del>- if (pos.atStartOfTree() || pos.atEndOfTree())
</del><ins>+ if (pos.atStartOfTree() || pos.atEndOfTree()) {
+ if (reachedBoundary)
+ *reachedBoundary = true;
</ins><span class="cx"> return VisiblePosition();
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> VisiblePosition right = VisiblePosition(pos, DOWNSTREAM);
</span><span class="cx"> ASSERT(right != *this);
</span><span class="lines">@@ -435,56 +452,78 @@
</span><span class="cx"> return right;
</span><span class="cx">
</span><span class="cx"> // FIXME: This may need to do something different from "after".
</span><del>- return honorEditingBoundaryAtOrAfter(right);
</del><ins>+ return honorEditingBoundaryAtOrAfter(right, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition VisiblePosition::honorEditingBoundaryAtOrBefore(const VisiblePosition &pos) const
</del><ins>+VisiblePosition VisiblePosition::honorEditingBoundaryAtOrBefore(const VisiblePosition &pos, bool* reachedBoundary) const
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> if (pos.isNull())
</span><span class="cx"> return pos;
</span><span class="cx">
</span><span class="cx"> Node* highestRoot = highestEditableRoot(deepEquivalent());
</span><span class="cx">
</span><span class="cx"> // Return empty position if pos is not somewhere inside the editable region containing this position
</span><del>- if (highestRoot && !pos.deepEquivalent().deprecatedNode()->isDescendantOf(highestRoot))
</del><ins>+ if (highestRoot && !pos.deepEquivalent().deprecatedNode()->isDescendantOf(highestRoot)) {
+ if (reachedBoundary)
+ *reachedBoundary = true;
</ins><span class="cx"> return VisiblePosition();
</span><del>-
</del><ins>+ }
+
</ins><span class="cx"> // Return pos itself if the two are from the very same editable region, or both are non-editable
</span><span class="cx"> // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
</span><span class="cx"> // to it is allowed. VisibleSelection::adjustForEditableContent has this problem too.
</span><del>- if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
</del><ins>+ if (highestEditableRoot(pos.deepEquivalent()) == highestRoot) {
+ if (reachedBoundary)
+ *reachedBoundary = *this == pos;
</ins><span class="cx"> return pos;
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> // Return empty position if this position is non-editable, but pos is editable
</span><span class="cx"> // FIXME: Move to the previous non-editable region.
</span><del>- if (!highestRoot)
</del><ins>+ if (!highestRoot) {
+ if (reachedBoundary)
+ *reachedBoundary = true;
</ins><span class="cx"> return VisiblePosition();
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> // Return the last position before pos that is in the same editable region as this position
</span><span class="cx"> return lastEditablePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition VisiblePosition::honorEditingBoundaryAtOrAfter(const VisiblePosition &pos) const
</del><ins>+VisiblePosition VisiblePosition::honorEditingBoundaryAtOrAfter(const VisiblePosition &pos, bool* reachedBoundary) const
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> if (pos.isNull())
</span><span class="cx"> return pos;
</span><span class="cx">
</span><span class="cx"> Node* highestRoot = highestEditableRoot(deepEquivalent());
</span><span class="cx">
</span><span class="cx"> // Return empty position if pos is not somewhere inside the editable region containing this position
</span><del>- if (highestRoot && !pos.deepEquivalent().deprecatedNode()->isDescendantOf(highestRoot))
</del><ins>+ if (highestRoot && !pos.deepEquivalent().deprecatedNode()->isDescendantOf(highestRoot)) {
+ if (reachedBoundary)
+ *reachedBoundary = true;
</ins><span class="cx"> return VisiblePosition();
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> // Return pos itself if the two are from the very same editable region, or both are non-editable
</span><span class="cx"> // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
</span><span class="cx"> // to it is allowed. VisibleSelection::adjustForEditableContent has this problem too.
</span><del>- if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
</del><ins>+ if (highestEditableRoot(pos.deepEquivalent()) == highestRoot) {
+ if (reachedBoundary)
+ *reachedBoundary = *this == pos;
</ins><span class="cx"> return pos;
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> // Return empty position if this position is non-editable, but pos is editable
</span><span class="cx"> // FIXME: Move to the next non-editable region.
</span><del>- if (!highestRoot)
</del><ins>+ if (!highestRoot) {
+ if (reachedBoundary)
+ *reachedBoundary = true;
</ins><span class="cx"> return VisiblePosition();
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> // Return the next position after pos that is in the same editable region as this position
</span><span class="cx"> return firstEditablePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot);
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisiblePositionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisiblePosition.h (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisiblePosition.h        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/editing/VisiblePosition.h        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -69,13 +69,13 @@
</span><span class="cx"> // FIXME: Change the following functions' parameter from a boolean to StayInEditableContent.
</span><span class="cx">
</span><span class="cx"> // next() and previous() will increment/decrement by a character cluster.
</span><del>- WEBCORE_EXPORT VisiblePosition next(EditingBoundaryCrossingRule = CanCrossEditingBoundary) const;
- WEBCORE_EXPORT VisiblePosition previous(EditingBoundaryCrossingRule = CanCrossEditingBoundary) const;
- VisiblePosition honorEditingBoundaryAtOrBefore(const VisiblePosition&) const;
- VisiblePosition honorEditingBoundaryAtOrAfter(const VisiblePosition&) const;
</del><ins>+ WEBCORE_EXPORT VisiblePosition next(EditingBoundaryCrossingRule = CanCrossEditingBoundary, bool* reachedBoundary = nullptr) const;
+ WEBCORE_EXPORT VisiblePosition previous(EditingBoundaryCrossingRule = CanCrossEditingBoundary, bool* reachedBoundary = nullptr) const;
+ VisiblePosition honorEditingBoundaryAtOrBefore(const VisiblePosition&, bool* reachedBoundary = nullptr) const;
+ VisiblePosition honorEditingBoundaryAtOrAfter(const VisiblePosition&, bool* reachedBoundary = nullptr) const;
</ins><span class="cx">
</span><del>- WEBCORE_EXPORT VisiblePosition left(bool stayInEditableContent = false) const;
- WEBCORE_EXPORT VisiblePosition right(bool stayInEditableContent = false) const;
</del><ins>+ WEBCORE_EXPORT VisiblePosition left(bool stayInEditableContent = false, bool* reachedBoundary = nullptr) const;
+ WEBCORE_EXPORT VisiblePosition right(bool stayInEditableContent = false, bool* reachedBoundary = nullptr) const;
</ins><span class="cx">
</span><span class="cx"> WEBCORE_EXPORT UChar32 characterAfter() const;
</span><span class="cx"> UChar32 characterBefore() const { return previous().characterAfter(); }
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.cpp (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.cpp        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/editing/VisibleUnits.cpp        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -774,31 +774,37 @@
</span><span class="cx"> : positionBeforeNode(startNode);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static VisiblePosition startOfLine(const VisiblePosition& c, LineEndpointComputationMode mode)
</del><ins>+static VisiblePosition startOfLine(const VisiblePosition& c, LineEndpointComputationMode mode, bool* reachedBoundary)
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> // TODO: this is the current behavior that might need to be fixed.
</span><span class="cx"> // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
</span><span class="cx"> VisiblePosition visPos = startPositionForLine(c, mode);
</span><span class="cx">
</span><span class="cx"> if (mode == UseLogicalOrdering) {
</span><span class="cx"> if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
</span><del>- if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
- return firstPositionInNode(editableRoot);
</del><ins>+ if (!editableRoot->contains(visPos.deepEquivalent().containerNode())) {
+ VisiblePosition newPosition = firstPositionInNode(editableRoot);
+ if (reachedBoundary)
+ *reachedBoundary = c == newPosition;
+ return newPosition;
+ }
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- return c.honorEditingBoundaryAtOrBefore(visPos);
</del><ins>+ return c.honorEditingBoundaryAtOrBefore(visPos, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // FIXME: Rename this function to reflect the fact it ignores bidi levels.
</span><span class="cx"> VisiblePosition startOfLine(const VisiblePosition& currentPosition)
</span><span class="cx"> {
</span><del>- return startOfLine(currentPosition, UseInlineBoxOrdering);
</del><ins>+ return startOfLine(currentPosition, UseInlineBoxOrdering, nullptr);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition logicalStartOfLine(const VisiblePosition& currentPosition)
</del><ins>+VisiblePosition logicalStartOfLine(const VisiblePosition& currentPosition, bool* reachedBoundary)
</ins><span class="cx"> {
</span><del>- return startOfLine(currentPosition, UseLogicalOrdering);
</del><ins>+ return startOfLine(currentPosition, UseLogicalOrdering, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static VisiblePosition endPositionForLine(const VisiblePosition& c, LineEndpointComputationMode mode)
</span><span class="lines">@@ -858,8 +864,10 @@
</span><span class="cx"> return a.isNotNull() && logicalStartOfLine(a) == logicalStartOfLine(b);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static VisiblePosition endOfLine(const VisiblePosition& c, LineEndpointComputationMode mode)
</del><ins>+static VisiblePosition endOfLine(const VisiblePosition& c, LineEndpointComputationMode mode, bool* reachedBoundary)
</ins><span class="cx"> {
</span><ins>+ if (reachedBoundary)
+ *reachedBoundary = false;
</ins><span class="cx"> // TODO: this is the current behavior that might need to be fixed.
</span><span class="cx"> // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
</span><span class="cx"> VisiblePosition visPos = endPositionForLine(c, mode);
</span><span class="lines">@@ -874,11 +882,15 @@
</span><span class="cx"> visPos = visPos.previous();
</span><span class="cx">
</span><span class="cx"> if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
</span><del>- if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
- return lastPositionInNode(editableRoot);
</del><ins>+ if (!editableRoot->contains(visPos.deepEquivalent().containerNode())) {
+ VisiblePosition newPosition = lastPositionInNode(editableRoot);
+ if (reachedBoundary)
+ *reachedBoundary = c == newPosition;
+ return newPosition;
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- return c.honorEditingBoundaryAtOrAfter(visPos);
</del><ins>+ return c.honorEditingBoundaryAtOrAfter(visPos, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Make sure the end of line is at the same line as the given input position. Else use the previous position to
</span><span class="lines">@@ -893,18 +905,18 @@
</span><span class="cx"> visPos = endPositionForLine(visPos, UseInlineBoxOrdering);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- return c.honorEditingBoundaryAtOrAfter(visPos);
</del><ins>+ return c.honorEditingBoundaryAtOrAfter(visPos, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // FIXME: Rename this function to reflect the fact it ignores bidi levels.
</span><span class="cx"> VisiblePosition endOfLine(const VisiblePosition& currentPosition)
</span><span class="cx"> {
</span><del>- return endOfLine(currentPosition, UseInlineBoxOrdering);
</del><ins>+ return endOfLine(currentPosition, UseInlineBoxOrdering, nullptr);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition logicalEndOfLine(const VisiblePosition& currentPosition)
</del><ins>+VisiblePosition logicalEndOfLine(const VisiblePosition& currentPosition, bool* reachedBoundary)
</ins><span class="cx"> {
</span><del>- return endOfLine(currentPosition, UseLogicalOrdering);
</del><ins>+ return endOfLine(currentPosition, UseLogicalOrdering, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool inSameLine(const VisiblePosition& a, const VisiblePosition& b)
</span><span class="lines">@@ -1440,14 +1452,14 @@
</span><span class="cx"> return p.isNotNull() && p.next().isNull();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
</del><ins>+VisiblePosition leftBoundaryOfLine(const VisiblePosition& c, TextDirection direction, bool* reachedBoundary)
</ins><span class="cx"> {
</span><del>- return direction == LTR ? logicalStartOfLine(c) : logicalEndOfLine(c);
</del><ins>+ return direction == LTR ? logicalStartOfLine(c, reachedBoundary) : logicalEndOfLine(c, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection direction)
</del><ins>+VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection direction, bool* reachedBoundary)
</ins><span class="cx"> {
</span><del>- return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
</del><ins>+ return direction == LTR ? logicalEndOfLine(c, reachedBoundary) : logicalStartOfLine(c, reachedBoundary);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static bool directionIsDownstream(SelectionDirection direction)
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.h (195948 => 195949)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.h        2016-02-01 03:10:00 UTC (rev 195948)
+++ trunk/Source/WebCore/editing/VisibleUnits.h        2016-02-01 04:09:02 UTC (rev 195949)
</span><span class="lines">@@ -60,11 +60,11 @@
</span><span class="cx"> WEBCORE_EXPORT bool inSameLine(const VisiblePosition &, const VisiblePosition &);
</span><span class="cx"> WEBCORE_EXPORT bool isStartOfLine(const VisiblePosition &);
</span><span class="cx"> WEBCORE_EXPORT bool isEndOfLine(const VisiblePosition &);
</span><del>-VisiblePosition logicalStartOfLine(const VisiblePosition &);
-VisiblePosition logicalEndOfLine(const VisiblePosition &);
</del><ins>+VisiblePosition logicalStartOfLine(const VisiblePosition &, bool* reachedBoundary = nullptr);
+VisiblePosition logicalEndOfLine(const VisiblePosition &, bool* reachedBoundary = nullptr);
</ins><span class="cx"> bool isLogicalEndOfLine(const VisiblePosition &);
</span><del>-VisiblePosition leftBoundaryOfLine(const VisiblePosition&, TextDirection);
-VisiblePosition rightBoundaryOfLine(const VisiblePosition&, TextDirection);
</del><ins>+VisiblePosition leftBoundaryOfLine(const VisiblePosition&, TextDirection, bool* reachedBoundary);
+VisiblePosition rightBoundaryOfLine(const VisiblePosition&, TextDirection, bool* reachedBoundary);
</ins><span class="cx">
</span><span class="cx"> // paragraphs (perhaps a misnomer, can be divided by line break elements)
</span><span class="cx"> WEBCORE_EXPORT VisiblePosition startOfParagraph(const VisiblePosition&, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
</span></span></pre>
</div>
</div>
</body>
</html>