Bug 970363 - Fix selection moving over readonly elements in contenteditble blocks. r=roc
authorTom Hindle <firefox@hindlemail.co.uk>
Wed, 12 Mar 2014 07:45:01 -0600
changeset 173448 f52f0588f43163eae13c98c76ff3059d92ff9628
parent 173447 1d6e179a67d7eb2df1b9b3a089fe1e88b988c617
child 173449 85ccf0c7e633521b21212dc522cacf3946fb090b
push id41005
push userryanvm@gmail.com
push dateThu, 13 Mar 2014 21:20:02 +0000
treeherdermozilla-inbound@7884913fe074 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs970363
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 970363 - Fix selection moving over readonly elements in contenteditble blocks. r=roc
layout/generic/nsFrame.cpp
layout/generic/test/mochitest.ini
layout/generic/test/test_bug970363.html
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6266,40 +6266,52 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
   
   switch (aPos->mAmount) {
     case eSelectCharacter:
     case eSelectCluster:
     {
       bool eatingNonRenderableWS = false;
       nsIFrame::FrameSearchResult peekSearchState = CONTINUE;
       bool jumpedLine = false;
+      bool movedOverNonSelectableText = false;
       
       while (peekSearchState != FOUND) {
         bool movingInFrameDirection =
           IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
 
         if (eatingNonRenderableWS)
           peekSearchState = current->PeekOffsetNoAmount(movingInFrameDirection, &offset); 
         else
           peekSearchState = current->PeekOffsetCharacter(movingInFrameDirection, &offset,
                                               aPos->mAmount == eSelectCluster);
 
+        movedOverNonSelectableText |= (peekSearchState == CONTINUE_UNSELECTABLE);
+
         if (peekSearchState != FOUND) {
           result =
             current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
                                            aPos->mJumpLines, aPos->mScrollViewStop,
                                            &current, &offset, &jumpedLine);
           if (NS_FAILED(result))
             return result;
 
           // If we jumped lines, it's as if we found a character, but we still need
           // to eat non-renderable content on the new line.
           if (jumpedLine)
             eatingNonRenderableWS = true;
         }
+
+        // Found frame, but because we moved over non selectable text we want the offset
+        // to be at the frame edge.
+        if (peekSearchState == FOUND && movedOverNonSelectableText)
+        {
+          int32_t start, end;
+          current->GetOffsets(start, end);
+          offset = aPos->mDirection == eDirNext ? 0 : end - start;
+        }
       }
 
       // Set outputs
       range = GetRangeForFrame(current);
       aPos->mResultFrame = current;
       aPos->mResultContent = range.content;
       // Output offset is relative to content, not frame
       aPos->mContentOffset = offset < 0 ? range.end : range.start + offset;
--- a/layout/generic/test/mochitest.ini
+++ b/layout/generic/test/mochitest.ini
@@ -87,16 +87,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug785324.html]
 [test_bug791616.html]
 skip-if = buildapp == 'b2g' # b2g(Target should not have scrolled - got 114.10000610351562, expected 115.39999389648438) b2g-debug(Target should not have scrolled - got 114.10000610351562, expected 115.39999389648438) b2g-desktop(Target should not have scrolled - got 114.10000610351562, expected 115.39999389648438)
 [test_bug831780.html]
 [test_bug841361.html]
 [test_bug904810.html]
 [test_bug938772.html]
+[test_bug970363.html]
 [test_contained_plugin_transplant.html]
 skip-if = os=='win'
 [test_image_selection.html]
 [test_image_selection_2.html]
 [test_invalidate_during_plugin_paint.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
 [test_movement_by_characters.html]
 [test_movement_by_words.html]
new file mode 100644
--- /dev/null
+++ b/layout/generic/test/test_bug970363.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=970363
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 970363</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=970363">Mozilla Bug 970363</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<div contenteditable="true" id='editablediv'>
+  <div id='t'>S<span contenteditable="false">readonly</span>E</div>
+</div>
+<pre id="test">
+
+ <script type="application/javascript">
+
+    /** Test for Bug 970363 **/
+
+    SimpleTest.waitForExplicitFinish();
+
+    SimpleTest.waitForFocus(function() {
+      var t = document.getElementById("t");
+      var editablediv = document.getElementById("editablediv");
+      var sel = window.getSelection();
+      editablediv.focus();
+      sel.collapse(t, 0);
+
+      // Move past the 'S' char.
+      synthesizeKey("VK_RIGHT", {});
+      // Move across the span.
+      synthesizeKey("VK_RIGHT", {});
+      // Insert an 'I' to show when IP currently is.
+      synthesizeKey("I", {});
+
+      is(t.textContent, "SreadonlyIE", "the 'I' char should be inserted between 'readonly' and 'E'");
+      SimpleTest.finish();
+    });
+
+  </script>
+
+</pre>
+</body>
+</html>