Skip to content
Browse files

Merge last green changeset of mozilla-inbound to mozilla-central

  • Loading branch information...
2 parents 0c13331 + 55a04fd commit 1e46984ef1d057ef93d700e5fc2d554427ab0961 Ed Morley committed Dec 20, 2011
Showing with 1,445 additions and 662 deletions.
  1. +1 −3 accessible/src/html/nsHTMLTableAccessible.cpp
  2. +6 −0 accessible/tests/mochitest/table/test_table_1.html
  3. +0 −3 b2g/app/b2g.js
  4. +112 −0 b2g/chrome/content/content.css
  5. +1 −0 b2g/chrome/jar.mn
  6. +2 −0 b2g/components/B2GComponents.manifest
  7. +0 −21 build/unix/gnu-ld-scripts/jemalloc-standalone-linkage-version-script
  8. +29 −0 content/base/public/nsINode.h
  9. +37 −1 content/base/public/nsIRange.h
  10. +1 −4 content/base/src/nsGenericDOMDataNode.h
  11. +8 −0 content/base/src/nsGenericElement.cpp
  12. +1 −0 content/base/src/nsGkAtomList.h
  13. +239 −17 content/base/src/nsRange.cpp
  14. +10 −12 content/base/src/nsRange.h
  15. +9 −0 content/base/src/nsTextNode.cpp
  16. +0 −1 extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
  17. +0 −5 js/src/configure.in
  18. +2 −2 layout/base/nsDisplayList.h
  19. +18 −49 layout/generic/nsFrame.cpp
  20. +0 −1 layout/generic/nsFrame.h
  21. +1 −2 layout/generic/nsFrameSelection.h
  22. +38 −54 layout/generic/nsGfxScrollFrame.cpp
  23. +5 −8 layout/generic/nsGfxScrollFrame.h
  24. +16 −27 layout/generic/nsIFrame.h
  25. +69 −73 layout/generic/nsSelection.cpp
  26. +7 −5 layout/generic/nsTextFrame.h
  27. +26 −78 layout/generic/nsTextFrameThebes.cpp
  28. +1 −6 layout/mathml/nsMathMLmoFrame.cpp
  29. +1 −9 layout/printing/nsPrintEngine.cpp
  30. +200 −0 layout/reftests/selection/dom-mutations-ref.html
  31. +250 −0 layout/reftests/selection/dom-mutations.html
  32. +1 −0 layout/reftests/selection/reftest.list
  33. +1 −39 layout/svg/base/src/nsSVGGlyphFrame.cpp
  34. +0 −3 layout/svg/base/src/nsSVGGlyphFrame.h
  35. +2 −5 layout/tables/nsTableCellFrame.cpp
  36. +2 −3 layout/tables/nsTableFrame.cpp
  37. +0 −8 layout/tables/nsTableOuterFrame.cpp
  38. +0 −5 layout/tables/nsTableOuterFrame.h
  39. +0 −2 layout/tools/reftest/jar.mn
  40. +0 −110 layout/tools/reftest/quit.js
  41. +35 −29 layout/tools/reftest/reftest.js
  42. +0 −2 layout/tools/reftest/reftest.xul
  43. +14 −1 mobile/android/base/AutoCompletePopup.java
  44. +84 −0 mobile/android/base/AwesomeBar.java
  45. +88 −18 mobile/android/base/GeckoAppShell.java
  46. +13 −2 mobile/android/base/Makefile.in
  47. +90 −0 mobile/android/base/gfx/BitmapUtils.java
  48. +4 −0 mobile/android/base/locales/en-US/android_strings.dtd
  49. BIN mobile/android/base/resources/drawable-hdpi-v8/home_bg.png
  50. BIN mobile/android/base/resources/drawable-hdpi-v8/home_star.png
  51. +0 −7 mobile/android/base/resources/drawable/awesomebar_tab_focus.xml
  52. +0 −7 mobile/android/base/resources/drawable/awesomebar_tab_focus_selected.xml
  53. +0 −7 mobile/android/base/resources/drawable/awesomebar_tab_press.xml
  54. +0 −7 mobile/android/base/resources/drawable/awesomebar_tab_press_selected.xml
  55. +0 −7 mobile/android/base/resources/drawable/awesomebar_tab_selected.xml
  56. +0 −7 mobile/android/base/resources/drawable/awesomebar_tab_unselected.xml
  57. +1 −1 mobile/android/base/resources/layout-v11/awesomebar_search_actionbar.xml
  58. +1 −1 mobile/android/base/resources/layout/awesomebar_search.xml
  59. +2 −2 mobile/android/base/resources/layout/awesomebar_tabs.xml
  60. +13 −0 mobile/android/base/resources/menu/awesomebar_contextmenu.xml
  61. +0 −1 mobile/android/base/resources/values/colors.xml
  62. +4 −0 mobile/android/base/strings.xml.in
  63. +0 −2 mobile/xul/app/mobile.js
  64. +0 −2 widget/public/LookAndFeel.h
  65. +0 −3 widget/src/xpwidgets/nsXPLookAndFeel.cpp
View
4 accessible/src/html/nsHTMLTableAccessible.cpp
@@ -106,9 +106,7 @@ nsHTMLTableCellAccessible::NativeState()
if (frame) {
state |= states::SELECTABLE;
- bool isSelected = false;
- frame->GetSelected(&isSelected);
- if (isSelected)
+ if (frame->IsSelected())
state |= states::SELECTED;
}
View
6 accessible/tests/mochitest/table/test_table_1.html
@@ -26,18 +26,24 @@
is(accTable.selectedCellCount, 1, "only one cell selected");
cell = getNode("col2a");
+ range = document.createRange();
range.selectNode(cell);
s.addRange(range);
cell = getNode("col2c");
+ range = document.createRange();
range.selectNode(cell);
s.addRange(range);
is(accTable.selectedColumnCount, 1, "only one column selected");
+
cell = getNode("row2a");
+ range = document.createRange();
range.selectNode(cell);
s.addRange(range);
cell = getNode("row2b");
+ range = document.createRange();
range.selectNode(cell);
s.addRange(range);
+ range = document.createRange();
cell = getNode("row2c");
range.selectNode(cell);
s.addRange(range);
View
3 b2g/app/b2g.js
@@ -49,9 +49,6 @@ pref("browser.homescreenURL", "file:///data/local/homescreen.html,file:///system
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
pref("browser.viewport.scaleRatio", -1);
-/* allow scrollbars to float above chrome ui */
-pref("ui.scrollbarsCanOverlapContent", 1);
-
/* disable text selection */
pref("browser.ignoreNativeFrameTextSelection", true);
View
112 b2g/chrome/content/content.css
@@ -0,0 +1,112 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla B2G.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+@namespace url("http://www.w3.org/1999/xhtml");
+@namespace xul url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+/* Style the scrollbars */
+xul|window xul|scrollbar {
+ display: none;
+}
+
+html xul|scrollbar {
+ display: block;
+}
+
+xul|scrollbar[orient="vertical"] {
+ -moz-appearance: none !important;
+ position: relative;
+ margin-left: -8px;
+ min-width: 8px;
+ max-width: 8px;
+ background-color: transparent !important;
+ background-image: none !important;
+ border: 0px solid transparent !important;
+}
+
+xul|scrollbar[orient="vertical"]:-moz-locale-dir(rtl) {
+ margin-left: 2px;
+ margin-right: -10px;
+}
+
+xul|scrollbar[orient="vertical"] xul|thumb {
+ max-width: 6px !important;
+ min-width: 6px !important;
+}
+
+xul|scrollbar[orient="horizontal"] {
+ -moz-appearance: none !important;
+ position: relative;
+ min-height: 8px;
+ max-height: 8px;
+ margin-top: -8px;
+ background-color: transparent !important;
+ background-image: none !important;
+ border: 0px solid transparent !important;
+}
+
+xul|scrollbar[orient="horizontal"] xul|thumb {
+ max-height: 6px !important;
+ min-height: 6px !important;
+}
+
+xul|scrollbox {
+ overflow-y: scroll;
+ overflow-x: scroll;
+}
+
+xul|scrollbarbutton {
+ min-height: 8px !important;
+ min-width: 8px !important;
+ -moz-appearance: none !important;
+ visibility: hidden;
+}
+
+xul|scrollbarbutton[sbattr="scrollbar-up-top"],
+xul|scrollbarbutton[sbattr="scrollbar-bottom-top"] {
+ display: none;
+}
+
+xul|thumb {
+ background-color: rgba(0, 0, 0, 0.4) !important;
+ -moz-border-top-colors: none !important;
+ -moz-border-bottom-colors: none !important;
+ -moz-border-right-colors: none !important;
+ -moz-border-left-colors: none !important;
+ border: 1px solid rgba(255, 255, 255, 0.4) !important;
+ -moz-border-radius: 3px;
+}
+
View
1 b2g/chrome/jar.mn
@@ -9,6 +9,7 @@ chrome.jar:
content/touch.js (content/touch.js)
content/commandUtil.js (content/commandUtil.js)
content/httpd.js (content/httpd.js)
+ content/content.css (content/content.css)
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
content/netError.xhtml (content/netError.xhtml)
View
2 b2g/components/B2GComponents.manifest
@@ -0,0 +1,2 @@
+# Scrollbars
+category agent-style-sheets browser-content-stylesheet chrome://browser/content/content.css
View
21 build/unix/gnu-ld-scripts/jemalloc-standalone-linkage-version-script
@@ -1,21 +0,0 @@
-{
- global:
- _malloc_postfork;
- _malloc_prefork;
- jemalloc_stats;
- malloc_usable_size;
- je_malloc_usable_size_in_advance;
- posix_memalign;
- free;
- realloc;
- calloc;
- malloc;
- memalign;
- valloc;
- __free_hook;
- __malloc_hook;
- __realloc_hook;
- __memalign_hook;
- _IO_stdin_used;
- local: *;
-};
View
29 content/base/public/nsINode.h
@@ -917,6 +917,18 @@ class nsINode : public nsIDOMEventTarget,
}
/**
+ * Returns true if |this| node is the common ancestor of the start/end
+ * nodes of a Range in a Selection or a descendant of such a common ancestor.
+ * This node is definitely not selected when |false| is returned, but it may
+ * or may not be selected when |true| is returned.
+ */
+ bool IsSelectionDescendant() const
+ {
+ return IsDescendantOfCommonAncestorForRangeInSelection() ||
+ IsCommonAncestorForRangeInSelection();
+ }
+
+ /**
* Get the root content of an editor. So, this node must be a descendant of
* an editor. Note that this should be only used for getting input or textarea
* editor's root content. This method doesn't support HTML editors.
@@ -1201,6 +1213,11 @@ class nsINode : public nsIDOMEventTarget,
ElementHasName,
// Set if the element might have a contenteditable attribute set.
ElementMayHaveContentEditableAttr,
+ // Set if the node is the common ancestor of the start/end nodes of a Range
+ // that is in a Selection.
+ NodeIsCommonAncestorForRangeInSelection,
+ // Set if the node is a descendant of a node with the above bit set.
+ NodeIsDescendantOfCommonAncestorForRangeInSelection,
// Guard value
BooleanFlagCount
};
@@ -1235,6 +1252,18 @@ class nsINode : public nsIDOMEventTarget,
bool HasName() const { return GetBoolFlag(ElementHasName); }
bool MayHaveContentEditableAttr() const
{ return GetBoolFlag(ElementMayHaveContentEditableAttr); }
+ bool IsCommonAncestorForRangeInSelection() const
+ { return GetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
+ void SetCommonAncestorForRangeInSelection()
+ { SetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
+ void ClearCommonAncestorForRangeInSelection()
+ { ClearBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
+ bool IsDescendantOfCommonAncestorForRangeInSelection() const
+ { return GetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
+ void SetDescendantOfCommonAncestorForRangeInSelection()
+ { SetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
+ void ClearDescendantOfCommonAncestorForRangeInSelection()
+ { ClearBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
View
38 content/base/public/nsIRange.h
@@ -40,8 +40,10 @@
#include "nsISupports.h"
#include "nsCOMPtr.h"
+#include "nsHashKeys.h"
#include "nsINode.h"
#include "nsIDOMRange.h"
+#include "nsTHashtable.h"
// IID for the nsIRange interface
#define NS_IRANGE_IID \
@@ -60,7 +62,8 @@ class nsIRange : public nsIDOMRange {
mEndOffset(0),
mIsPositioned(false),
mIsDetached(false),
- mMaySpanAnonymousSubtrees(false)
+ mMaySpanAnonymousSubtrees(false),
+ mInSelection(false)
{
}
@@ -110,6 +113,33 @@ class nsIRange : public nsIDOMRange {
mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
}
+ /**
+ * Return true iff this range is part of at least one Selection object
+ * and isn't detached.
+ */
+ bool IsInSelection() const
+ {
+ return mInSelection;
+ }
+
+ /**
+ * Called when the range is added/removed from a Selection.
+ */
+ void SetInSelection(bool aInSelection)
+ {
+ if (mInSelection == aInSelection || mIsDetached) {
+ return;
+ }
+ mInSelection = aInSelection;
+ nsINode* commonAncestor = GetCommonAncestor();
+ NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
+ if (mInSelection) {
+ RegisterCommonAncestor(commonAncestor);
+ } else {
+ UnregisterCommonAncestor(commonAncestor);
+ }
+ }
+
virtual nsINode* GetCommonAncestor() const = 0;
virtual void Reset() = 0;
@@ -128,7 +158,12 @@ class nsIRange : public nsIDOMRange {
// To support the font inspector API
NS_IMETHOD GetUsedFontFaces(nsIDOMFontFaceList** aResult) = 0;
+ typedef nsTHashtable<nsPtrHashKey<nsIRange> > RangeHashTable;
protected:
+ void RegisterCommonAncestor(nsINode* aNode);
+ void UnregisterCommonAncestor(nsINode* aNode);
+ nsINode* IsValidBoundary(nsINode* aNode);
+
nsCOMPtr<nsINode> mRoot;
nsCOMPtr<nsINode> mStartParent;
nsCOMPtr<nsINode> mEndParent;
@@ -138,6 +173,7 @@ class nsIRange : public nsIDOMRange {
bool mIsPositioned;
bool mIsDetached;
bool mMaySpanAnonymousSubtrees;
+ bool mInSelection;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIRange, NS_IRANGE_IID)
View
5 content/base/src/nsGenericDOMDataNode.h
@@ -63,11 +63,8 @@
// whitespace, we may need to reframe it (or its ancestors).
#define NS_REFRAME_IF_WHITESPACE (1 << (NODE_TYPE_SPECIFIC_BITS_OFFSET + 1))
-// This bit is set to indicate that the text may be part of a selection.
-#define NS_TEXT_IN_SELECTION (1 << (NODE_TYPE_SPECIFIC_BITS_OFFSET + 2))
-
// Make sure we have enough space for those bits
-PR_STATIC_ASSERT(NODE_TYPE_SPECIFIC_BITS_OFFSET + 2 < 32);
+PR_STATIC_ASSERT(NODE_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
class nsIDOMAttr;
class nsIDOMEventListener;
View
8 content/base/src/nsGenericElement.cpp
@@ -91,6 +91,9 @@
#endif /* MOZ_XUL */
#include "nsFrameManager.h"
#include "nsFrameSelection.h"
+#ifdef DEBUG
+#include "nsIRange.h"
+#endif
#include "nsBindingManager.h"
#include "nsXBLBinding.h"
@@ -4933,6 +4936,11 @@ nsGenericElement::List(FILE* out, PRInt32 aIndent,
fprintf(out, " state=[%llx]", State().GetInternalValue());
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
+ if (IsCommonAncestorForRangeInSelection()) {
+ nsIRange::RangeHashTable* ranges =
+ static_cast<nsIRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
+ fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
+ }
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
fprintf(out, " refcount=%d<", mRefCnt.get());
View
1 content/base/src/nsGkAtomList.h
@@ -836,6 +836,7 @@ GK_ATOM(queryset, "queryset")
GK_ATOM(querytype, "querytype")
GK_ATOM(radio, "radio")
GK_ATOM(radiogroup, "radiogroup")
+GK_ATOM(range, "range")
GK_ATOM(readonly, "readonly")
GK_ATOM(rect, "rect")
GK_ATOM(rectangle, "rectangle")
View
256 content/base/src/nsRange.cpp
@@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
+ * Mats Palmgren <matspal@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -156,6 +157,69 @@ nsRange::CompareNodeToRange(nsINode* aNode, nsIRange* aRange,
return NS_OK;
}
+struct FindSelectedRangeData
+{
+ nsINode* mNode;
+ nsIRange* mResult;
+ PRUint32 mStartOffset;
+ PRUint32 mEndOffset;
+};
+
+static PLDHashOperator
+FindSelectedRange(nsPtrHashKey<nsIRange>* aEntry, void* userArg)
+{
+ nsIRange* range = aEntry->GetKey();
+ if (range->IsInSelection() && !range->Collapsed()) {
+ FindSelectedRangeData* data = static_cast<FindSelectedRangeData*>(userArg);
+ PRInt32 cmp = nsContentUtils::ComparePoints(data->mNode, data->mEndOffset,
+ range->GetStartParent(),
+ range->StartOffset());
+ if (cmp == 1) {
+ cmp = nsContentUtils::ComparePoints(data->mNode, data->mStartOffset,
+ range->GetEndParent(),
+ range->EndOffset());
+ if (cmp == -1) {
+ data->mResult = range;
+ return PL_DHASH_STOP;
+ }
+ }
+ }
+ return PL_DHASH_NEXT;
+}
+
+static nsINode*
+GetNextRangeCommonAncestor(nsINode* aNode)
+{
+ while (aNode && !aNode->IsCommonAncestorForRangeInSelection()) {
+ if (!aNode->IsDescendantOfCommonAncestorForRangeInSelection()) {
+ return nsnull;
+ }
+ aNode = aNode->GetNodeParent();
+ }
+ return aNode;
+}
+
+/* static */ bool
+nsRange::IsNodeSelected(nsINode* aNode, PRUint32 aStartOffset,
+ PRUint32 aEndOffset)
+{
+ NS_PRECONDITION(aNode, "bad arg");
+
+ FindSelectedRangeData data = { aNode, nsnull, aStartOffset, aEndOffset };
+ nsINode* n = GetNextRangeCommonAncestor(aNode);
+ NS_ASSERTION(n || !aNode->IsSelectionDescendant(),
+ "orphan selection descendant");
+ for (; n; n = GetNextRangeCommonAncestor(n->GetNodeParent())) {
+ RangeHashTable* ranges =
+ static_cast<RangeHashTable*>(n->GetProperty(nsGkAtoms::range));
+ ranges->EnumerateEntries(FindSelectedRange, &data);
+ if (data.mResult) {
+ return true;
+ }
+ }
+ return false;
+}
+
/******************************************************
* non members
******************************************************/
@@ -225,8 +289,10 @@ NS_NewRange(nsIDOMRange** aResult)
nsRange::~nsRange()
{
- DoSetRange(nsnull, 0, nsnull, 0, nsnull);
+ NS_ASSERTION(!IsInSelection(), "deleting nsRange that is in use");
+
// we want the side effects (releases and list removals)
+ DoSetRange(nsnull, 0, nsnull, 0, nsnull);
}
/******************************************************
@@ -260,6 +326,94 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+static void
+RangeHashTableDtor(void* aObject, nsIAtom* aPropertyName, void* aPropertyValue,
+ void* aData)
+{
+ nsIRange::RangeHashTable* ranges =
+ static_cast<nsIRange::RangeHashTable*>(aPropertyValue);
+ delete ranges;
+}
+
+static void MarkDescendants(nsINode* aNode)
+{
+ // Set NodeIsDescendantOfCommonAncestorForRangeInSelection on aNode's
+ // descendants unless aNode is already marked as a range common ancestor
+ // or a descendant of one, in which case all of our descendants have the
+ // bit set already.
+ if (!aNode->IsSelectionDescendant()) {
+ // don't set the Descendant bit on |aNode| itself
+ nsINode* node = aNode->GetNextNode(aNode);
+ while (node) {
+ node->SetDescendantOfCommonAncestorForRangeInSelection();
+ if (!node->IsCommonAncestorForRangeInSelection()) {
+ node = node->GetNextNode(aNode);
+ } else {
+ // optimize: skip this sub-tree since it's marked already.
+ node = node->GetNextNonChildNode(aNode);
+ }
+ }
+ }
+}
+
+static void UnmarkDescendants(nsINode* aNode)
+{
+ // Unset NodeIsDescendantOfCommonAncestorForRangeInSelection on aNode's
+ // descendants unless aNode is a descendant of another range common ancestor.
+ // Also, exclude descendants of range common ancestors (but not the common
+ // ancestor itself).
+ if (!aNode->IsDescendantOfCommonAncestorForRangeInSelection()) {
+ // we know |aNode| doesn't have any bit set
+ nsINode* node = aNode->GetNextNode(aNode);
+ while (node) {
+ node->ClearDescendantOfCommonAncestorForRangeInSelection();
+ if (!node->IsCommonAncestorForRangeInSelection()) {
+ node = node->GetNextNode(aNode);
+ } else {
+ // We found an ancestor of an overlapping range, skip its descendants.
+ node = node->GetNextNonChildNode(aNode);
+ }
+ }
+ }
+}
+
+void
+nsIRange::RegisterCommonAncestor(nsINode* aNode)
+{
+ NS_PRECONDITION(aNode, "bad arg");
+ NS_ASSERTION(IsInSelection(), "registering range not in selection");
+
+ MarkDescendants(aNode);
+
+ RangeHashTable* ranges =
+ static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
+ if (!ranges) {
+ ranges = new RangeHashTable;
+ ranges->Init();
+ aNode->SetProperty(nsGkAtoms::range, ranges, RangeHashTableDtor);
+ }
+ ranges->PutEntry(this);
+ aNode->SetCommonAncestorForRangeInSelection();
+}
+
+void
+nsIRange::UnregisterCommonAncestor(nsINode* aNode)
+{
+ NS_PRECONDITION(aNode, "bad arg");
+ NS_ASSERTION(aNode->IsCommonAncestorForRangeInSelection(), "wrong node");
+ RangeHashTable* ranges =
+ static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
+ NS_ASSERTION(ranges->GetEntry(this), "unknown range");
+
+ if (ranges->Count() == 1) {
+ aNode->ClearCommonAncestorForRangeInSelection();
+ aNode->DeleteProperty(nsGkAtoms::range);
+ UnmarkDescendants(aNode);
+ } else {
+ ranges->RemoveEntry(this);
+ }
+}
+
/******************************************************
* nsIMutationObserver implementation
******************************************************/
@@ -293,6 +447,15 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
if (NS_UNLIKELY(aContent == mRoot)) {
newRoot = IsValidBoundary(newStartNode);
}
+
+ bool isCommonAncestor = IsInSelection() && mStartParent == mEndParent;
+ if (isCommonAncestor) {
+ UnregisterCommonAncestor(mStartParent);
+ RegisterCommonAncestor(newStartNode);
+ }
+ if (mStartParent->IsDescendantOfCommonAncestorForRangeInSelection()) {
+ newStartNode->SetDescendantOfCommonAncestorForRangeInSelection();
+ }
} else {
// If boundary is inside changed text, position it before change
// else adjust start offset for the change in length.
@@ -317,6 +480,16 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
"mEndOffset is beyond the end of this node");
newEndOffset = static_cast<PRUint32>(mEndOffset) - aInfo->mChangeStart;
newEndNode = aInfo->mDetails->mNextSibling;
+
+ bool isCommonAncestor = IsInSelection() && mStartParent == mEndParent;
+ if (isCommonAncestor && !newStartNode) {
+ // The split occurs inside the range.
+ UnregisterCommonAncestor(mStartParent);
+ RegisterCommonAncestor(mStartParent->GetParent());
+ newEndNode->SetDescendantOfCommonAncestorForRangeInSelection();
+ } else if (mEndParent->IsDescendantOfCommonAncestorForRangeInSelection()) {
+ newEndNode->SetDescendantOfCommonAncestorForRangeInSelection();
+ }
} else {
mEndOffset = static_cast<PRUint32>(mEndOffset) <= aInfo->mChangeEnd ?
aInfo->mChangeStart :
@@ -355,11 +528,29 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
newEndOffset = mEndOffset;
}
DoSetRange(newStartNode, newStartOffset, newEndNode, newEndOffset,
- newRoot ? newRoot : mRoot.get()
-#ifdef DEBUG
- , !newEndNode->GetParent() || !newStartNode->GetParent()
-#endif
- );
+ newRoot ? newRoot : mRoot.get(),
+ !newEndNode->GetParent() || !newStartNode->GetParent());
+ }
+}
+
+void
+nsRange::ContentAppended(nsIDocument* aDocument,
+ nsIContent* aContainer,
+ nsIContent* aFirstNewContent,
+ PRInt32 aNewIndexInContainer)
+{
+ NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
+
+ nsINode* container = NODE_FROM(aContainer, aDocument);
+ if (container->IsSelectionDescendant() && IsInSelection()) {
+ nsINode* child = aFirstNewContent;
+ while (child) {
+ if (!child->IsDescendantOfCommonAncestorForRangeInSelection()) {
+ MarkDescendants(child);
+ child->SetDescendantOfCommonAncestorForRangeInSelection();
+ }
+ child = child->GetNextSibling();
+ }
}
}
@@ -380,6 +571,11 @@ nsRange::ContentInserted(nsIDocument* aDocument,
if (container == mEndParent && aIndexInContainer < mEndOffset) {
++mEndOffset;
}
+ if (container->IsSelectionDescendant() &&
+ !aChild->IsDescendantOfCommonAncestorForRangeInSelection()) {
+ MarkDescendants(aChild);
+ aChild->SetDescendantOfCommonAncestorForRangeInSelection();
+ }
}
void
@@ -392,6 +588,8 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
nsINode* container = NODE_FROM(aContainer, aDocument);
+ bool gravitateStart = false;
+ bool gravitateEnd = false;
// Adjust position if a sibling was removed...
if (container == mStartParent) {
@@ -401,8 +599,7 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
}
// ...or gravitate if an ancestor was removed.
else if (nsContentUtils::ContentIsDescendantOf(mStartParent, aChild)) {
- mStartParent = container;
- mStartOffset = aIndexInContainer;
+ gravitateStart = true;
}
// Do same thing for end boundry.
@@ -412,8 +609,20 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
}
}
else if (nsContentUtils::ContentIsDescendantOf(mEndParent, aChild)) {
- mEndParent = container;
- mEndOffset = aIndexInContainer;
+ gravitateEnd = true;
+ }
+
+ if (gravitateStart || gravitateEnd) {
+ DoSetRange(gravitateStart ? container : mStartParent.get(),
+ gravitateStart ? aIndexInContainer : mStartOffset,
+ gravitateEnd ? container : mEndParent.get(),
+ gravitateEnd ? aIndexInContainer : mEndOffset,
+ mRoot);
+ }
+ if (container->IsSelectionDescendant() &&
+ aChild->IsDescendantOfCommonAncestorForRangeInSelection()) {
+ aChild->ClearDescendantOfCommonAncestorForRangeInSelection();
+ UnmarkDescendants(aChild);
}
}
@@ -507,11 +716,7 @@ static PRUint32 GetNodeLength(nsINode *aNode)
void
nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
nsINode* aEndN, PRInt32 aEndOffset,
- nsINode* aRoot
-#ifdef DEBUG
- , bool aNotInsertedYet
-#endif
- )
+ nsINode* aRoot, bool aNotInsertedYet)
{
NS_PRECONDITION((aStartN && aEndN && aRoot) ||
(!aStartN && !aEndN && !aRoot),
@@ -545,12 +750,29 @@ nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
aRoot->AddMutationObserver(this);
}
}
-
+ bool checkCommonAncestor = (mStartParent != aStartN || mEndParent != aEndN) &&
+ IsInSelection() && !aNotInsertedYet;
+ nsINode* oldCommonAncestor = checkCommonAncestor ? GetCommonAncestor() : nsnull;
mStartParent = aStartN;
mStartOffset = aStartOffset;
mEndParent = aEndN;
mEndOffset = aEndOffset;
mIsPositioned = !!mStartParent;
+ if (checkCommonAncestor) {
+ nsINode* newCommonAncestor = GetCommonAncestor();
+ if (newCommonAncestor != oldCommonAncestor) {
+ if (oldCommonAncestor) {
+ UnregisterCommonAncestor(oldCommonAncestor);
+ }
+ if (newCommonAncestor) {
+ RegisterCommonAncestor(newCommonAncestor);
+ } else {
+ NS_ASSERTION(mIsDetached, "unexpected disconnected nodes");
+ mInSelection = false;
+ }
+ }
+ }
+
// This needs to be the last thing this function does. See comment
// in ParentChainChanged.
mRoot = aRoot;
@@ -664,7 +886,7 @@ nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent)
return NS_ERROR_NOT_INITIALIZED;
}
-nsINode* nsRange::IsValidBoundary(nsINode* aNode)
+nsINode* nsIRange::IsValidBoundary(nsINode* aNode)
{
if (!aNode) {
return nsnull;
View
22 content/base/src/nsRange.h
@@ -77,9 +77,7 @@ class nsRange : public nsIRange,
public nsStubMutationObserver
{
public:
- nsRange()
- {
- }
+ nsRange(){}
virtual ~nsRange();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -116,14 +114,13 @@ class nsRange : public nsIRange,
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
private:
// no copy's or assigns
nsRange(const nsRange&);
nsRange& operator=(const nsRange&);
- nsINode* IsValidBoundary(nsINode* aNode);
-
/**
* Cut or delete the range's contents.
*
@@ -157,16 +154,17 @@ class nsRange : public nsIRange,
bool *outNodeBefore,
bool *outNodeAfter);
+ static bool IsNodeSelected(nsINode* aNode, PRUint32 aStartOffset,
+ PRUint32 aEndOffset);
+
protected:
+ // CharacterDataChanged set aNotInsertedYet to true to disable an assertion
+ // and suppress re-registering a range common ancestor node since
+ // the new text node of a splitText hasn't been inserted yet.
+ // CharacterDataChanged does the re-registering when needed.
void DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
nsINode* aEndN, PRInt32 aEndOffset,
- nsINode* aRoot
-#ifdef DEBUG
- // CharacterDataChanged use this to disable an assertion since
- // the new text node of a splitText hasn't been inserted yet.
- , bool aNotInsertedYet = false
-#endif
- );
+ nsINode* aRoot, bool aNotInsertedYet = false);
};
// Make a new nsIDOMRange object
View
9 content/base/src/nsTextNode.cpp
@@ -46,6 +46,9 @@
#include "nsIAttribute.h"
#include "nsIDocument.h"
#include "nsThreadUtils.h"
+#ifdef DEBUG
+#include "nsIRange.h"
+#endif
using namespace mozilla::dom;
@@ -224,6 +227,12 @@ nsTextNode::List(FILE* out, PRInt32 aIndent) const
fprintf(out, "Text@%p", static_cast<const void*>(this));
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
+ if (IsCommonAncestorForRangeInSelection()) {
+ typedef nsTHashtable<nsPtrHashKey<nsIRange> > RangeHashTable;
+ RangeHashTable* ranges =
+ static_cast<RangeHashTable*>(GetProperty(nsGkAtoms::range));
+ fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
+ }
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
fprintf(out, " refcount=%d<", mRefCnt.get());
View
1 extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -969,7 +969,6 @@ WordSplitState::FindSpecialWord()
if (protocol.EqualsIgnoreCase("http") ||
protocol.EqualsIgnoreCase("https") ||
protocol.EqualsIgnoreCase("news") ||
- protocol.EqualsIgnoreCase("ftp") ||
protocol.EqualsIgnoreCase("file") ||
protocol.EqualsIgnoreCase("javascript") ||
protocol.EqualsIgnoreCase("ftp")) {
View
5 js/src/configure.in
@@ -2852,11 +2852,6 @@ MOZ_ARG_DISABLE_BOOL(polyic,
[ --disable-polyic Disable use of PICs by JIT compiler],
ENABLE_POLYIC= )
-MOZ_ARG_ENABLE_BOOL(tracejit,
-[ --enable-tracejit Deprecated, does nothing],
- ENABLE_TRACEJIT=,
- ENABLE_TRACEJIT= )
-
MOZ_ARG_ENABLE_BOOL(methodjit-spew,
[ --enable-methodjit-spew Enable method JIT spew support],
ENABLE_METHODJIT_SPEW=1,
View
4 layout/base/nsDisplayList.h
@@ -217,8 +217,8 @@ class nsDisplayListBuilder {
void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
/**
- * Calling this setter makes us exclude all leaf frames that does
- * not have the NS_FRAME_SELECTED_CONTENT bit.
+ * Calling this setter makes us exclude all leaf frames that aren't
+ * selected.
*/
void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
View
67 layout/generic/nsFrame.cpp
@@ -91,6 +91,7 @@
#include "nsFrameTraversal.h"
#include "nsStyleChangeList.h"
#include "nsIDOMRange.h"
+#include "nsRange.h"
#include "nsITableLayout.h" //selection necessity
#include "nsITableCellLayout.h"// "
#include "nsITextControlFrame.h"
@@ -444,8 +445,7 @@ nsFrame::Init(nsIContent* aContent,
nsFrameState state = aPrevInFlow->GetStateBits();
// Make bits that are currently off (see constructor) the same:
- mState |= state & (NS_FRAME_SELECTED_CONTENT |
- NS_FRAME_INDEPENDENT_SELECTION |
+ mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
NS_FRAME_IS_SPECIAL |
NS_FRAME_MAY_BE_TRANSFORMED);
}
@@ -568,8 +568,7 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
shell->NotifyDestroyingFrame(this);
- if ((mState & NS_FRAME_EXTERNAL_REFERENCE) ||
- (mState & NS_FRAME_SELECTED_CONTENT)) {
+ if (mState & NS_FRAME_EXTERNAL_REFERENCE) {
shell->ClearFrameRefs(this);
}
@@ -1204,10 +1203,7 @@ nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
PRUint16 aContentType)
{
-//check frame selection state
- if ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) != NS_FRAME_SELECTED_CONTENT)
- return NS_OK;
- if (!IsVisibleForPainting(aBuilder))
+ if (!IsSelected() || !IsVisibleForPainting(aBuilder))
return NS_OK;
nsPresContext* presContext = PresContext();
@@ -1922,7 +1918,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
if (childType != nsGkAtoms::placeholderFrame &&
aBuilder->GetSelectedFramesOnly() &&
child->IsLeaf() &&
- !(child->GetStateBits() & NS_FRAME_SELECTED_CONTENT)) {
+ !aChild->IsSelected()) {
return NS_OK;
}
@@ -2493,9 +2489,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
// drag the selected region to some other app.
SelectionDetails *details = 0;
- bool isSelected = ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
-
- if (isSelected)
+ if (GetContent()->IsSelectionDescendant())
{
bool inSelection = false;
details = frameselection->LookUpSelection(offsets.content, 0,
@@ -5199,8 +5193,9 @@ nsIFrame::IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder) {
bool
nsIFrame::IsVisibleInSelection(nsISelection* aSelection)
{
- if ((mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT)
- return true;
+ if (!GetContent() || !GetContent()->IsSelectionDescendant()) {
+ return false;
+ }
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
bool vis;
@@ -5256,11 +5251,11 @@ nsIFrame::GetFrameSelection()
}
const nsFrameSelection*
-nsIFrame::GetConstFrameSelection()
+nsIFrame::GetConstFrameSelection() const
{
- nsIFrame *frame = this;
+ nsIFrame* frame = const_cast<nsIFrame*>(this);
while (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)) {
- nsITextControlFrame *tcf = do_QueryFrame(frame);
+ nsITextControlFrame* tcf = do_QueryFrame(frame);
if (tcf) {
return tcf->GetOwnedFrameSelection();
}
@@ -5338,39 +5333,13 @@ nsFrame::DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32
}
#endif
-void
-nsIFrame::SetSelected(bool aSelected, SelectionType aType)
-{
- NS_ASSERTION(!GetPrevContinuation(),
- "Should only be called on first in flow");
- if (aType != nsISelectionController::SELECTION_NORMAL)
- return;
-
- // check whether style allows selection
- bool selectable;
- IsSelectable(&selectable, nsnull);
- if (!selectable)
- return;
-
- for (nsIFrame* f = this; f; f = f->GetNextContinuation()) {
- if (aSelected) {
- AddStateBits(NS_FRAME_SELECTED_CONTENT);
- } else {
- RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
- }
-
- // Repaint this frame subtree's entire area
- InvalidateFrameSubtree();
- }
-}
-
-NS_IMETHODIMP
-nsFrame::GetSelected(bool *aSelected) const
+bool
+nsIFrame::IsFrameSelected() const
{
- if (!aSelected )
- return NS_ERROR_NULL_POINTER;
- *aSelected = !!(mState & NS_FRAME_SELECTED_CONTENT);
- return NS_OK;
+ NS_ASSERTION(!GetContent() || GetContent()->IsSelectionDescendant(),
+ "use the public IsSelected() instead");
+ return nsRange::IsNodeSelected(GetContent(), 0,
+ GetContent()->GetChildCount());
}
NS_IMETHODIMP
View
1 layout/generic/nsFrame.h
@@ -232,7 +232,6 @@ class nsFrame : public nsBox
NS_IMETHOD GetOffsetFromView(nsPoint& aOffset, nsIView** aView) const;
virtual nsIAtom* GetType() const;
- NS_IMETHOD GetSelected(bool *aSelected) const;
NS_IMETHOD IsSelectable(bool* aIsSelectable, PRUint8* aSelectStyle) const;
NS_IMETHOD GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon);
View
3 layout/generic/nsFrameSelection.h
@@ -596,7 +596,6 @@ class nsFrameSelection : public nsISupports {
*/
nsresult MaintainSelection(nsSelectionAmount aAmount = eSelectNoAmount);
-
nsFrameSelection();
void StartBatchChanges();
@@ -606,7 +605,7 @@ class nsFrameSelection : public nsISupports {
nsIPresShell *GetShell()const { return mShell; }
- void DisconnectFromPresShell() { StopAutoScrollTimer(); mShell = nsnull; }
+ void DisconnectFromPresShell();
private:
nsresult TakeFocus(nsIContent *aNewFocus,
PRUint32 aContentOffset,
View
92 layout/generic/nsGfxScrollFrame.cpp
@@ -1474,9 +1474,6 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsContainerFrame* aOuter,
, mCollapsedResizer(false)
, mShouldBuildLayer(false)
{
- // lookup if we're allowed to overlap the content from the look&feel object
- mScrollbarsCanOverlapContent =
- LookAndFeel::GetInt(LookAndFeel::eIntID_ScrollbarsCanOverlapContent) != 0;
mScrollingActive = IsAlwaysActive();
}
@@ -1879,32 +1876,35 @@ AppendToTop(nsDisplayListBuilder* aBuilder, nsDisplayList* aDest,
}
}
-nsresult
-nsGfxScrollFrameInner::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
- const nsDisplayListSet& aLists,
- const nsDisplayListCollection& aDest,
- bool& aCreateLayer)
+void
+nsGfxScrollFrameInner::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists,
+ bool& aCreateLayer,
+ bool aPositioned)
{
- nsresult rv = NS_OK;
- bool hasResizer = HasResizer();
for (nsIFrame* kid = mOuter->GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
- if (kid != mScrolledFrame) {
- if (kid == mResizerBox && hasResizer) {
- // skip the resizer as this will be drawn later on top of the scrolled content
- continue;
- }
- rv = mOuter->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aDest,
- nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
- NS_ENSURE_SUCCESS(rv, rv);
- // DISPLAY_CHILD_FORCE_STACKING_CONTEXT put everything into the
- // PositionedDescendants list.
- ::AppendToTop(aBuilder, aLists.BorderBackground(),
- aDest.PositionedDescendants(), kid,
- aCreateLayer);
- }
+ if (kid == mScrolledFrame ||
+ (kid->GetStyleDisplay()->IsPositioned() != aPositioned))
+ continue;
+
+ nsDisplayListCollection partList;
+ mOuter->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, partList,
+ nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
+
+ // Don't append textarea resizers to the positioned descendants because
+ // we don't want them to float on top of overlapping elements.
+ bool appendToPositioned = aPositioned && !(kid == mResizerBox && !mIsRoot);
+
+ nsDisplayList* dest = appendToPositioned ?
+ aLists.PositionedDescendants() : aLists.BorderBackground();
+
+ // DISPLAY_CHILD_FORCE_STACKING_CONTEXT put everything into
+ // partList.PositionedDescendants().
+ ::AppendToTop(aBuilder, dest,
+ partList.PositionedDescendants(), kid,
+ aCreateLayer);
}
- return rv;
}
bool
@@ -1984,15 +1984,15 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
bool createLayersForScrollbars = mIsRoot &&
mOuter->PresContext()->IsRootContentDocument();
- nsDisplayListCollection scrollParts;
- if (!mScrollbarsCanOverlapContent) {
- // Now display the scrollbars and scrollcorner. These parts are drawn
- // in the border-background layer, on top of our own background and
- // borders and underneath borders and backgrounds of later elements
- // in the tree.
- AppendScrollPartsTo(aBuilder, aDirtyRect, aLists,
- scrollParts, createLayersForScrollbars);
- }
+ // Now display the scrollbars and scrollcorner. These parts are drawn
+ // in the border-background layer, on top of our own background and
+ // borders and underneath borders and backgrounds of later elements
+ // in the tree.
+ // Note that this does not apply for overlay scrollbars; those are drawn
+ // in the positioned-elements layer on top of everything else by the call
+ // to AppendScrollPartsTo(..., true) further down.
+ AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, createLayersForScrollbars,
+ false);
// Overflow clipping can never clip frames outside our subtree, so there
// is no need to worry about whether we are a moving frame that might clip
@@ -2062,25 +2062,9 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
true, mIsRoot);
NS_ENSURE_SUCCESS(rv, rv);
- if (mScrollbarsCanOverlapContent) {
- AppendScrollPartsTo(aBuilder, aDirtyRect, aLists,
- scrollParts, createLayersForScrollbars);
- }
-
- if (HasResizer()) {
- rv = mOuter->BuildDisplayListForChild(aBuilder, mResizerBox, aDirtyRect, scrollParts,
- nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
- NS_ENSURE_SUCCESS(rv, rv);
- // DISPLAY_CHILD_FORCE_STACKING_CONTEXT puts everything into the
- // PositionedDescendants list.
- // The resizer is positioned and has maximum z-index; we put it in
- // PositionedDescendants() for the root frame to ensure that it appears
- // above all content, bug 631337.
- ::AppendToTop(aBuilder,
- mIsRoot ? aLists.PositionedDescendants() : aLists.Content(),
- scrollParts.PositionedDescendants(), mResizerBox,
- createLayersForScrollbars);
- }
+ // Now display overlay scrollbars and the resizer, if we have one.
+ AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, createLayersForScrollbars,
+ true);
return NS_OK;
}
View
13 layout/generic/nsGfxScrollFrame.h
@@ -98,11 +98,11 @@ class nsGfxScrollFrameInner : public nsIReflowCallback {
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
- nsresult AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
- const nsRect& aDirtyRect,
- const nsDisplayListSet& aLists,
- const nsDisplayListCollection& aDest,
- bool& aCreateLayer);
+ void AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists,
+ bool& aCreateLayer,
+ bool aPositioned);
bool GetBorderRadii(nscoord aRadii[8]) const;
@@ -324,9 +324,6 @@ class nsGfxScrollFrameInner : public nsIReflowCallback {
// If true, we should be prepared to scroll using this scrollframe
// by placing descendant content into its own layer(s)
bool mScrollingActive:1;
- // If true, scrollbars are stacked on the top of the display list and can
- // float above the content as a result
- bool mScrollbarsCanOverlapContent:1;
// If true, the resizer is collapsed and not displayed
bool mCollapsedResizer:1;
View
43 layout/generic/nsIFrame.h
@@ -199,8 +199,8 @@ typedef PRUint64 nsFrameState;
// e.g., it is absolutely positioned or floated
#define NS_FRAME_OUT_OF_FLOW NS_FRAME_STATE_BIT(8)
-// If this bit is set, then the frame reflects content that may be selected
-#define NS_FRAME_SELECTED_CONTENT NS_FRAME_STATE_BIT(9)
+// This bit is available for re-use.
+//#define NS_FRAME_SELECTED_CONTENT NS_FRAME_STATE_BIT(9)
// If this bit is set, then the frame is dirty and needs to be reflowed.
// This bit is set when the frame is first created.
@@ -261,6 +261,7 @@ typedef PRUint64 nsFrameState;
// Bits 20-31 and 60-63 of the frame state are reserved for implementations.
#define NS_FRAME_IMPL_RESERVED nsFrameState(0xF0000000FFF00000)
+#define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED
// This bit is set on floats whose parent does not contain their
// placeholder. This can happen for two reasons: (1) the float was
@@ -297,9 +298,6 @@ typedef PRUint64 nsFrameState;
// This is only set during painting
#define NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO NS_FRAME_STATE_BIT(40)
-// Bits 0-19 and bits 32-59 of the frame state are reserved by this API.
-#define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED
-
// Box layout bits
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)
@@ -580,6 +578,12 @@ class nsIFrame : public nsQueryFrame
protected:
/**
+ * Return true if the frame is part of a Selection.
+ * Helper method to implement the public IsSelected() API.
+ */
+ virtual bool IsFrameSelected() const;
+
+ /**
* Implements Destroy(). Do not call this directly except from within a
* DestroyFrom() implementation.
*
@@ -2305,25 +2309,13 @@ class nsIFrame : public nsQueryFrame
*/
virtual PRIntn GetSkipSides() const { return 0; }
- /** Selection related calls
- */
- /**
- * Called to set the selection status of the frame.
- *
- * This must be called on the primary frame, but all continuations
- * will be affected the same way.
- *
- * This sets or clears NS_FRAME_SELECTED_CONTENT for each frame in the
- * continuation chain, if the frames are currently selectable.
- * The frames are unconditionally invalidated, if this selection type
- * is supported at all.
- * @param aSelected is it selected?
- * @param aType the selection type of the selection that you are setting on the frame
+ /**
+ * @returns true if this frame is selected.
*/
- virtual void SetSelected(bool aSelected,
- SelectionType aType);
-
- NS_IMETHOD GetSelected(bool *aSelected) const = 0;
+ bool IsSelected() const {
+ return (GetContent() && GetContent()->IsSelectionDescendant()) ?
+ IsFrameSelected() : false;
+ }
/**
* called to discover where this frame, or a parent frame has user-select style
@@ -2352,10 +2344,7 @@ class nsIFrame : public nsQueryFrame
* GetConstFrameSelection returns an object which methods are safe to use for
* example in nsIFrame code.
*/
- const nsFrameSelection* GetConstFrameSelection();
-
- /** EndSelection related calls
- */
+ const nsFrameSelection* GetConstFrameSelection() const;
/**
* called to find the previous/next character, word, or line returns the actual
View
142 layout/generic/nsSelection.cpp
@@ -267,7 +267,6 @@ class nsTypedSelection : public nsISelectionPrivate,
nsresult StopAutoScrollTimer();
-
private:
friend class nsAutoScrollTimer;
@@ -1702,8 +1701,8 @@ nsFrameSelection::HandleDrag(nsIFrame *aFrame, nsPoint aPoint)
if (!offsets.content)
return;
- if ((newFrame->GetStateBits() & NS_FRAME_SELECTED_CONTENT) &&
- AdjustForMaintainedSelection(offsets.content, offsets.offset))
+ if (newFrame->IsSelected() &&
+ AdjustForMaintainedSelection(offsets.content, offsets.offset))
return;
// Adjust offsets according to maintained amount
@@ -1911,7 +1910,6 @@ printf(" * TakeFocus - moving into new cell\n");
}
-
SelectionDetails*
nsFrameSelection::LookUpSelection(nsIContent *aContent,
PRInt32 aContentOffset,
@@ -2478,8 +2476,7 @@ printf("HandleTableSelection: Mouse down event\n");
// Check if new cell is already selected
nsIFrame *cellFrame = childContent->GetPrimaryFrame();
if (!cellFrame) return NS_ERROR_NULL_POINTER;
- result = cellFrame->GetSelected(&isSelected);
- if (NS_FAILED(result)) return result;
+ isSelected = cellFrame->IsSelected();
}
else
{
@@ -3377,6 +3374,16 @@ nsFrameSelection::GetDelayedCaretData()
return nsnull;
}
+void
+nsFrameSelection::DisconnectFromPresShell()
+{
+ StopAutoScrollTimer();
+ for (PRInt32 i = 0; i < nsISelectionController::NUM_SELECTIONTYPES; i++) {
+ mDomSelections[i]->Clear(nsnull);
+ }
+ mShell = nsnull;
+}
+
//END nsISelection interface implementations
#if 0
@@ -3406,6 +3413,11 @@ nsTypedSelection::~nsTypedSelection()
{
setAnchorFocusRange(-1);
+ PRUint32 count = mRanges.Length();
+ for (PRUint32 i = 0; i < count; ++i) {
+ mRanges[i].mRange->SetInSelection(false);
+ }
+
if (mAutoScrollTimer) {
mAutoScrollTimer->Stop();
mAutoScrollTimer = nsnull;
@@ -3730,6 +3742,8 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
if (mRanges.Length() == 0) {
if (!mRanges.AppendElement(RangeData(aItem)))
return NS_ERROR_OUT_OF_MEMORY;
+ aItem->SetInSelection(true);
+
if (aOutIndex)
*aOutIndex = 0;
return NS_OK;
@@ -3767,6 +3781,7 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
// The new range doesn't overlap any existing ranges
if (!mRanges.InsertElementAt(startIndex, RangeData(aItem)))
return NS_ERROR_OUT_OF_MEMORY;
+ aItem->SetInSelection(true);
if (aOutIndex)
*aOutIndex = startIndex;
return NS_OK;
@@ -3788,6 +3803,9 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
}
// Remove all the overlapping ranges
+ for (PRInt32 i = startIndex; i < endIndex; ++i) {
+ mRanges[i].mRange->SetInSelection(false);
+ }
mRanges.RemoveElementsAt(startIndex, endIndex - startIndex);
nsTArray<RangeData> temp;
@@ -3811,6 +3829,10 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
if (!mRanges.InsertElementsAt(startIndex, temp))
return NS_ERROR_OUT_OF_MEMORY;
+ for (PRUint32 i = 0; i < temp.Length(); ++i) {
+ temp[i].mRange->SetInSelection(true);
+ }
+
*aOutIndex = startIndex + insertionPoint;
return NS_OK;
}
@@ -3837,6 +3859,7 @@ nsTypedSelection::RemoveItem(nsIRange *aItem)
return NS_ERROR_INVALID_ARG;
mRanges.RemoveElementAt(idx);
+ aItem->SetInSelection(false);
return NS_OK;
}
@@ -3860,8 +3883,9 @@ nsTypedSelection::Clear(nsPresContext* aPresContext)
{
setAnchorFocusRange(-1);
- for (PRInt32 i = 0; i < (PRInt32)mRanges.Length(); i ++) {
- selectFrames(aPresContext, mRanges[i].mRange, 0);
+ for (PRUint32 i = 0; i < mRanges.Length(); ++i) {
+ mRanges[i].mRange->SetInSelection(false);
+ selectFrames(aPresContext, mRanges[i].mRange, false);
}
mRanges.Clear();
@@ -4274,42 +4298,29 @@ nsTypedSelection::SelectAllFramesForContent(nsIContentIterator *aInnerIter,
nsIContent *aContent,
bool aSelected)
{
- if (!mFrameSelection)
- return NS_OK; // nothing to do
- nsIPresShell* shell = mFrameSelection->GetShell();
- if (!shell)
- return NS_OK;
- nsresult result;
- if (!aInnerIter)
- return NS_ERROR_NULL_POINTER;
- result = aInnerIter->Init(aContent);
+ nsresult result = aInnerIter->Init(aContent);
nsIFrame *frame;
if (NS_SUCCEEDED(result))
{
// First select frame of content passed in
frame = aContent->GetPrimaryFrame();
- if (frame)
- {
- frame->SetSelected(aSelected, mType);
- if (mFrameSelection->GetTableCellSelection())
- {
- nsITableCellLayout *tcl = do_QueryFrame(frame);
- if (tcl)
- {
- return NS_OK;
- }
- }
+ if (frame && frame->GetType() == nsGkAtoms::textFrame) {
+ nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
+ textFrame->SetSelectedRange(0, aContent->GetText()->GetLength(), aSelected, mType);
}
// Now iterated through the child frames and set them
- while (!aInnerIter->IsDone())
- {
+ while (!aInnerIter->IsDone()) {
nsCOMPtr<nsIContent> innercontent =
do_QueryInterface(aInnerIter->GetCurrentNode());
frame = innercontent->GetPrimaryFrame();
- if (frame)
- {
- frame->SetSelected(aSelected, mType);
+ if (frame) {
+ if (frame->GetType() == nsGkAtoms::textFrame) {
+ nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
+ textFrame->SetSelectedRange(0, innercontent->GetText()->GetLength(), aSelected, mType);
+ } else {
+ frame->InvalidateFrameSubtree(); // frame continuations?
+ }
}
aInnerIter->Next();
@@ -4321,21 +4332,23 @@ nsTypedSelection::SelectAllFramesForContent(nsIContentIterator *aInnerIter,
return NS_ERROR_FAILURE;
}
-
-
//the idea of this helper method is to select, deselect "top to bottom" traversing through the frames
nsresult
nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bool aFlags)
{
- if (!mFrameSelection || !aPresContext)
+ if (!mFrameSelection || !aPresContext || !aPresContext->GetPresShell())
return NS_OK; // nothing to do
- nsIPresShell *presShell = aPresContext->GetPresShell();
- if (!presShell)
- return NS_OK;
- nsCOMPtr<nsIDOMRange> domRange = do_QueryInterface(aRange);
- if (!domRange || !aPresContext)
- return NS_ERROR_NULL_POINTER;
+ if (mFrameSelection->GetTableCellSelection()) {
+ nsINode* node = aRange->GetCommonAncestor();
+ nsCOMPtr<nsIContent> content = do_QueryInterface(node);
+ nsIFrame* frame = content ? content->GetPrimaryFrame()
+ : aPresContext->FrameManager()->GetRootFrame();
+ if (frame) {
+ frame->InvalidateFrameSubtree();
+ }
+ return NS_OK;
+ }
nsresult result;
nsCOMPtr<nsIContentIterator> iter = do_CreateInstance(
@@ -4348,8 +4361,7 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
kCContentIteratorCID,
&result);
- if ((NS_SUCCEEDED(result)) && iter && inneriter)
- {
+ if ((NS_SUCCEEDED(result)) && iter) {
result = iter->Init(aRange);
// loop through the content iterator for each content node
@@ -4360,8 +4372,7 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
if (!content)
return NS_ERROR_UNEXPECTED;
- if (content->IsNodeOfType(nsINode::eTEXT))
- {
+ if (content->IsNodeOfType(nsINode::eTEXT)) {
nsIFrame* frame = content->GetPrimaryFrame();
// The frame could be an SVG text frame, in which case we'll ignore
// it.
@@ -4380,13 +4391,9 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
}
iter->First();
-
- while (!iter->IsDone())
- {
+ while (!iter->IsDone()) {
content = do_QueryInterface(iter->GetCurrentNode());
-
SelectAllFramesForContent(inneriter, content, aFlags);
-
iter->Next();
}
@@ -4413,6 +4420,7 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
return result;
}
+
// nsTypedSelection::LookUpSelection
//
// This function is called when a node wants to know where the selection is
@@ -4785,13 +4793,7 @@ nsTypedSelection::AddRange(nsIRange* aRange)
nsRefPtr<nsPresContext> presContext;
GetPresContext(getter_AddRefs(presContext));
-
- // Ensure all frames are properly constructed for selectFrames, bug 602331.
- nsIPresShell* presShell = presContext ? presContext->GetPresShell() : nsnull;
- if (presShell) {
- presShell->FlushPendingNotifications(Flush_Frames);
- }
- selectFrames(presContext, aRange, true);
+ selectFrames(presContext, aRange, true);
if (!mFrameSelection)
return NS_OK;//nothing to do
@@ -4926,27 +4928,21 @@ nsTypedSelection::Collapse(nsINode* aParentNode, PRInt32 aOffset)
return result;
#ifdef DEBUG_SELECTION
- if (aParentNode)
- {
- nsCOMPtr<nsIContent>content;
- content = do_QueryInterface(aParentNode);
- if (!content)
- return NS_ERROR_FAILURE;
-
- printf ("Sel. Collapse to %p %s %d\n", content.get(),
- nsAtomCString(content->Tag()).get(), aOffset);
- }
- else {
- printf ("Sel. Collapse set to null parent.\n");
+ if (aParentNode) {
+ nsCOMPtr<nsIContent> content = do_QueryInterface(aParentNode);
+ nsCOMPtr<nsIDocument> doc = do_QueryInterface(aParentNode);
+ printf ("Sel. Collapse to %p %s %d\n", aParentNode,
+ content ? nsAtomCString(content->Tag()).get()
+ : (doc ? "DOCUMENT" : "???"),
+ aOffset);
}
#endif
-
result = AddItem(range);
- setAnchorFocusRange(0);
- selectFrames(presContext, range, true);
if (NS_FAILED(result))
return result;
+ setAnchorFocusRange(0);
+ selectFrames(presContext, range, true);
return mFrameSelection->NotifySelectionListeners(GetType());
}
View
12 layout/generic/nsTextFrame.h
@@ -165,11 +165,7 @@ class nsTextFrame : public nsFrame {
* false otherwise
* @param aType the type of selection added or removed
*/
- virtual void SetSelected(bool aSelected,
- SelectionType aType);
- void SetSelectedRange(PRUint32 aStart,
- PRUint32 aEnd,
- bool aSelected,
+ void SetSelectedRange(PRUint32 aStart, PRUint32 aEnd, bool aSelected,
SelectionType aType);
virtual bool PeekOffsetNoAmount(bool aForward, PRInt32* aOffset);
@@ -476,6 +472,12 @@ class nsTextFrame : public nsFrame {
nscoord mAscent;
gfxTextRun* mTextRun;
+ /**
+ * Return true if the frame is part of a Selection.
+ * Helper method to implement the public IsSelected() API.
+ */
+ virtual bool IsFrameSelected() const;
+
// The caller of this method must call DestroySelectionDetails() on the
// return value, if that return value is not null. Calling
// DestroySelectionDetails() on a null value is still OK, just not necessary.
View
104 layout/generic/nsTextFrameThebes.cpp
@@ -92,6 +92,7 @@
#include "nsFrameSelection.h"
#include "nsISelection.h"
#include "nsIDOMRange.h"
+#include "nsRange.h"
#include "nsCSSRendering.h"
#include "nsContentUtils.h"
#include "nsLineBreaker.h"
@@ -3689,6 +3690,7 @@ nsTextFrame::Init(nsIContent* aContent,
// Since our content has a frame now, this flag is no longer needed.
aContent->UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE);
+
// We're not a continuing frame.
// mContentOffset = 0; not necessary since we get zeroed out at init
return nsFrame::Init(aContent, aParent, aPrevInFlow);
@@ -4314,6 +4316,9 @@ SelectionDetails*
nsTextFrame::GetSelectionDetails()
{
const nsFrameSelection* frameSelection = GetConstFrameSelection();
+ if (frameSelection->GetTableCellSelection()) {
+ return nsnull;
+ }
if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
SelectionDetails* details =
frameSelection->LookUpSelection(mContent, GetContentOffset(),
@@ -4575,7 +4580,7 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
}
// When this frame is not selected, the text-decoration area must be in
// frame bounds.
- if (!(GetStateBits() & NS_FRAME_SELECTED_CONTENT) ||
+ if (!IsSelected() ||
!CombineSelectionUnderlineRect(aPresContext, *aVisualOverflowRect))
return;
AddStateBits(TEXT_SELECTION_UNDERLINE_OVERFLOWED);
@@ -5025,13 +5030,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
*aAllTypes = allTypes;
if (!allTypes) {
- // Nothing is selected in the given text range.
- if (aContentLength == aProvider.GetOriginalLength()) {
- // It's the full text range so we can remove the FRAME_SELECTED_CONTENT
- // bit to avoid going through this slow path until something is selected
- // in this frame again.
- RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
- }
+ // Nothing is selected in the given text range. XXX can this still occur?
return false;
}
@@ -5179,23 +5178,18 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
nsTextPaintStyle& aTextPaintStyle,
const nsCharClipDisplayItem::ClipEdges& aClipEdges)
{
+ NS_ASSERTION(GetContent()->IsSelectionDescendant(), "wrong paint path");
+
SelectionDetails* details = GetSelectionDetails();
if (!details) {
- if (aContentLength == aProvider.GetOriginalLength()) {
- // It's the full text range so we can remove the FRAME_SELECTED_CONTENT
- // bit to avoid going through this slow path until something is selected
- // in this frame again.
- RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
- }
return false;
}
SelectionType allTypes;
if (!PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
aProvider, aContentOffset, aContentLength,
aTextPaintStyle, details, &allTypes,
- aClipEdges))
- {
+ aClipEdges)) {
DestroySelectionDetails(details);
return false;
}
@@ -5412,15 +5406,16 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y,
aDirtyRect.width, aDirtyRect.height);
// Fork off to the (slower) paint-with-selection path if necessary.
- if (nsLayoutUtils::GetNonGeneratedAncestor(this)->GetStateBits() & NS_FRAME_SELECTED_CONTENT) {
+ if (IsSelected()) {
gfxSkipCharsIterator tmp(provider.GetStart());
PRInt32 contentOffset = tmp.ConvertSkippedToOriginal(startOffset);
PRInt32 contentLength =
tmp.ConvertSkippedToOriginal(startOffset + maxLength) - contentOffset;
if (PaintTextWithSelection(ctx, framePt, textBaselinePt, dirtyRect,
provider, contentOffset, contentLength,
- textPaintStyle, clipEdges))
+ textPaintStyle, clipEdges)) {
return;
+ }
}
nscolor foregroundColor = textPaintStyle.GetTextColor();
@@ -5610,8 +5605,7 @@ bool
nsTextFrame::IsVisibleInSelection(nsISelection* aSelection)
{
// Check the quick way first
- bool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
- if (!isSelected)
+ if (!GetContent()->IsSelectionDescendant())
return false;
SelectionDetails* details = GetSelectionDetails();
@@ -5801,17 +5795,17 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
return !aRect.IsEmpty() && !givenRect.Contains(aRect);
}
-void
-nsTextFrame::SetSelected(bool aSelected,
- SelectionType aType)
+bool
+nsTextFrame::IsFrameSelected() const
{
- SetSelectedRange(0, mContent->GetText()->GetLength(), aSelected, aType);
+ NS_ASSERTION(!GetContent() || GetContent()->IsSelectionDescendant(),
+ "use the public IsSelected() instead");
+ return nsRange::IsNodeSelected(GetContent(), GetContentOffset(),
+ GetContentEnd());
}
void
-nsTextFrame::SetSelectedRange(PRUint32 aStart,
- PRUint32 aEnd,
- bool aSelected,
+nsTextFrame::SetSelectedRange(PRUint32 aStart, PRUint32 aEnd, bool aSelected,
SelectionType aType)
{
NS_ASSERTION(!GetPrevContinuation(), "Should only be called for primary frame");
@@ -5825,35 +5819,18 @@ nsTextFrame::SetSelectedRange(PRUint32 aStart,
// check whether style allows selection
bool selectable;
IsSelectable(&selectable, nsnull);
- if (!selectable)
+ if (!selectable) {
return;
+ }
}
- bool anySelected = false;
-
nsTextFrame* f = this;
while (f && f->GetContentEnd() <= PRInt32(aStart)) {
- if (f->GetStateBits() & NS_FRAME_SELECTED_CONTENT) {
- anySelected = true;
- }
f = static_cast<nsTextFrame*>(f->GetNextContinuation());
}
nsPresContext* presContext = PresContext();
while (f && f->GetContentOffset() < PRInt32(aEnd)) {
- if (aSelected) {
- f->AddStateBits(NS_FRAME_SELECTED_CONTENT);
- anySelected = true;
- } else { // we need to see if any other selection is available.
- SelectionDetails *details = f->GetSelectionDetails();
- if (details) {
- anySelected = true;
- DestroySelectionDetails(details);
- } else {
- f->RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
- }
- }
-
// We may need to reflow to recompute the overflow area for
// spellchecking or IME underline if their underline is thicker than
// the normal decoration line.
@@ -5874,22 +5851,6 @@ nsTextFrame::SetSelectedRange(PRUint32 aStart,
f = static_cast<nsTextFrame*>(f->GetNextContinuation());
}
-
- // Scan remaining continuations to see if any are selected
- while (f && !anySelected) {
- if (f->GetStateBits() & NS_FRAME_SELECTED_CONTENT) {
- anySelected = true;
- }
- f = static_cast<nsTextFrame*>(f->GetNextContinuation());
- }
-
- if (anySelected) {
- mContent->SetFlags(NS_TEXT_IN_SELECTION);
- } else {
- // This is only legal because there is only one presentation for the
- // content with a selection
- mContent->UnsetFlags(NS_TEXT_IN_SELECTION);
- }
}
NS_IMETHODIMP
@@ -7623,16 +7584,6 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
SetLength(contentLength, &aLineLayout, ALLOW_FRAME_CREATION_AND_DESTRUCTION);
- if (mContent->HasFlag(NS_TEXT_IN_SELECTION)) {
- SelectionDetails* details = GetSelectionDetails();
- if (details) {
- AddStateBits(NS_FRAME_SELECTED_CONTENT);
- DestroySelectionDetails(details);
- } else {
- RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
- }
- }
-
Invalidate(aMetrics.VisualOverflow());
#ifdef NOISY_REFLOW
@@ -7996,12 +7947,9 @@ nsTextFrame::List(FILE* out, PRInt32 aIndent) const
// Output the rect and state
fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
- if (0 != mState) {
- if (mState & NS_FRAME_SELECTED_CONTENT) {
- fprintf(out, " [state=%016llx] SELECTED", mState);
- } else {
- fprintf(out, " [state=%016llx]", mState);
- }
+ fprintf(out, " [state=%016llx]", mState);
+ if (IsSelected()) {
+ fprintf(out, " SELECTED");
}
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
if (HasOverflowAreas()) {
View
7 layout/mathml/nsMathMLmoFrame.cpp
@@ -89,12 +89,7 @@ bool
nsMathMLmoFrame::IsFrameInSelection(nsIFrame* aFrame)
{
NS_ASSERTION(aFrame, "null arg");
- if (!aFrame)
- return false;
-
- bool isSelected = false;
- aFrame->GetSelected(&isSelected);
- if (!isSelected)
+ if (!aFrame || !aFrame->IsSelected())
return false;
const nsFrameSelection* frameSelection = aFrame->GetConstFrameSelection();
View
10 layout/printing/nsPrintEngine.cpp
@@ -2546,15 +2546,7 @@ nsPrintEngine::FindSelectionBoundsWithList(nsPresContext* aPresContext,
aRect += aParentFrame->GetPosition();
for (; !aChildFrames.AtEnd(); aChildFrames.Next()) {
nsIFrame* child = aChildFrames.get();
- // only leaf frames have this bit flipped
- // then check the hard way
- bool isSelected = (child->GetStateBits() & NS_FRAME_SELECTED_CONTENT)
- == NS_FRAME_SELECTED_CONTENT;
- if (isSelected) {
- isSelected = child->IsVisibleForPainting();
- }
-
- if (isSelected) {
+ if (child->IsSelected() && child->IsVisibleForPainting()) {
nsRect r = child->GetRect();
if (aStartFrame == nsnull) {
aStartFrame = child;
View
200 layout/reftests/selection/dom-mutations-ref.html
@@ -0,0 +1,200 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=619273
+-->
+<head>
+ <title>Test for Bug 619273</title>
+<script type="application/javascript;version=1.7">
+/** Test DOM mutations inside selection **/
+function createDOM(doc) {
+ let s = doc.createElement('span');
+ s.appendChild(doc.createTextNode('|'))
+ let s2 = doc.createElement('span');
+ s2.appendChild(doc.createTextNode('z'))
+ s.appendChild(s2)
+ return s;
+}
+
+var tests_done = 0;
+var tests = [
+ function(win,doc,sel) {
+ doc.body.innerHTML = '.I<br>B<br>C|z'
+ let a = doc.body.firstChild;
+ let r = doc.createRange();
+ r.setStart(a, 1);
+ r.setEnd(a, 2);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = '.I<br>B<br>C|z'
+ let a = doc.body.firstChild;
+ let r = doc.createRange();
+ r.setStart(doc.firstChild, 0);
+ r.setEnd(a, 2);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>.B<br>C|z'
+ let a = doc.body.firstChild;
+ let b = doc.body.childNodes[2];
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(a, 0);
+ r.setEnd(c, 1);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>.B<br>C|z'
+ let b = doc.body.childNodes[2];
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(doc.body, 0);
+ r.setEnd(c, 1);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>.B<br>C|z'
+ let b = doc.body.childNodes[2];
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(doc, 0);
+ r.setEnd(c, 1);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>B<br>.C|z'
+ let a = doc.body.firstChild;
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(a, 0);
+ r.setEnd(c, 2);
+ sel.addRange(r);
+ },
+
+ function(win,doc,sel) {
+ doc.body.innerHTML = '|z|zI<br>B<br>C'
+ let a = doc.body.firstChild;
+ let r = doc.createRange();
+ r.setStart(a, 4);
+ r.setEnd(a, 5);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = '|z|zI<br>B<br>C'
+ let a = doc.body.firstChild;
+ let r = doc.createRange();
+ r.setStart(doc.firstChild, 0);
+ r.setEnd(a, 5);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>|z|zB<br>C'
+ let a = doc.body.firstChild;
+ let b = doc.body.childNodes[2];
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(a, 0);
+ r.setEnd(c, 1);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>|z|zB<br>C'
+ let b = doc.body.childNodes[2];
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(doc.body, 0);
+ r.setEnd(c, 1);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>|z|zB<br>C'
+ let b = doc.body.childNodes[2];
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(doc, 0);
+ r.setEnd(c, 1);
+ sel.addRange(r);
+ },
+ function(win,doc,sel) {
+ doc.body.innerHTML = 'I<br>B<br>|z|zC'
+ let a = doc.body.firstChild;
+ let c = doc.body.childNodes[4];
+ let r = doc.createRange();
+ r.setStart(a, 0);
+ r.setEnd(c, 5);
+ sel.addRange(r);