Bug 635618 part 1. Only get computed style in IsElementVisible if we end up in a situation where we're waiting on lazy frame construction. r=ehsan
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 28 Nov 2011 07:53:15 -0500
changeset 81672 c6adf89aa521af3b3a5a7ccaa8231cdc0808a652
parent 81671 0d33f892f63a268a30d61dfdb89f2bb262a31906
child 81673 b4614bcc4ad886ffcb1b1ccadacc474a820bf8b7
push idunknown
push userunknown
push dateunknown
reviewersehsan
bugs635618
milestone11.0a1
Bug 635618 part 1. Only get computed style in IsElementVisible if we end up in a situation where we're waiting on lazy frame construction. r=ehsan
editor/libeditor/base/nsEditor.cpp
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -3609,21 +3609,62 @@ nsEditor::IsTextInDirtyFrameVisible(nsID
   // virtual method
   //
   // If this is a simple non-html editor,
   // the best we can do is to assume it's visible.
 
   return true;
 }
 
-static bool
-IsElementVisible(nsIContent* aContent) {
-  mozilla::dom::Element* element = aContent->AsElement();
+static inline bool
+IsElementVisible(dom::Element* aElement)
+{
+  if (aElement->GetPrimaryFrame()) {
+    // It's visible, for our purposes
+    return true;
+  }
+
+  nsIContent *cur = aElement;
+  for (; ;) {
+    cur = cur->GetFlattenedTreeParent();
+    if (!cur) {
+      // None of our ancestors have lazy bits set, so we shouldn't have a frame
+      return false;
+    }
+
+    if (cur->GetPrimaryFrame()) {
+      // None of our ancestors up to the nearest ancestor with a frame have
+      // lazy bits; that means we won't get a frame
+      return false;
+    }
+
+    if (cur->HasFlag(NODE_NEEDS_FRAME)) {
+      // Double-check that the parent doesn't have a leaf frame
+      nsIContent *parent = cur->GetFlattenedTreeParent();
+      if (parent) {
+        NS_ASSERTION(parent->GetPrimaryFrame(),
+                     "Why does our parent not have a frame?");
+        if (parent->GetPrimaryFrame()->IsLeaf()) {
+          // No frame for us
+          return false;
+        }
+      }
+
+      // |cur| will get a frame sometime.  What does that mean for us?
+      // |We have to figure that out!
+      break;
+    }
+  }
+
+  // Now it might be that we have no frame because we're in a
+  // display:none subtree, or it might be that we're just dealing with
+  // lazy frame construction and it hasn't happened yet.  Check which
+  // one it is.
   nsRefPtr<nsStyleContext> styleContext =
-    nsComputedDOMStyle::GetStyleContextForElementNoFlush(element,
+    nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
                                                          nsnull, nsnull);
   if (styleContext) {
     return styleContext->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_NONE;
   }
   return false;
 }
 
 bool 
@@ -3633,19 +3674,22 @@ nsEditor::IsEditable(nsIDOMNode *aNode)
 
   if (IsMozEditorBogusNode(aNode) || !IsModifiableNode(aNode)) return false;
 
   // see if it has a frame.  If so, we'll edit it.
   // special case for textnodes: frame must have width.
   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   if (content)
   {
-    if (content->IsElement() &&
-        !IsElementVisible(content)) // If the element is invisible, it's not editable
+    if (content->IsElement() && !IsElementVisible(content->AsElement())) {
+      // If the element has no frame, it's not editable.  Note that we
+      // need to check IsElement() here, because some of our tests
+      // rely on frameless textnodes being visible.
       return false;
+    }
     if (!content->IsNodeOfType(nsINode::eTEXT))
       return true;  // not a text node; not invisible
 
     return IsTextInDirtyFrameVisible(aNode);
   }
   return false;  // didn't pass any editability test
 }