Bug 449076: hang with 100% CPU on keyboard arrow trough text field. r+sr=roc.
authorUri Bernstein <uriber@gmail.com>
Thu, 09 Oct 2008 12:22:30 +0200
changeset 20200 729436f1f0d3f929891bc1f9cd5b2b367d5a3713
parent 20199 abd911498db31587f9116891c54af7b5a311b671
child 20201 5ab2c2b2f3a06887ff4dc475b75c0ec6c3d7d17c
push idunknown
push userunknown
push dateunknown
bugs449076
milestone1.9.1b2pre
Bug 449076: hang with 100% CPU on keyboard arrow trough text field. r+sr=roc.
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5072,17 +5072,17 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
       break;
     }
     case eSelectLine :
     {
       nsCOMPtr<nsILineIteratorNavigator> iter; 
       nsIFrame *blockFrame = this;
 
       while (NS_FAILED(result)){
-        PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, &blockFrame);
+        PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, aPos->mScrollViewStop, &blockFrame);
         if (thisLine < 0) 
           return  NS_ERROR_FAILURE;
         result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(iter));
         NS_ASSERTION(NS_SUCCEEDED(result) && iter, "GetLineNumber() succeeded but no block frame?");
 
         int edgeCase = 0;//no edge case. this should look at thisLine
         
         PRBool doneLooping = PR_FALSE;//tells us when no more block frames hit.
@@ -5166,17 +5166,17 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
       return PeekOffsetParagraph(aPos);
 
     case eSelectBeginLine:
     case eSelectEndLine:
     {
       nsCOMPtr<nsILineIteratorNavigator> it;
       // Adjusted so that the caret can't get confused when content changes
       nsIFrame* blockFrame = AdjustFrameForSelectionStyles(this);
-      PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, &blockFrame);
+      PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, aPos->mScrollViewStop, &blockFrame);
       if (thisLine < 0)
         return NS_ERROR_FAILURE;
       result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
       NS_ASSERTION(NS_SUCCEEDED(result) && it, "GetLineNumber() succeeded but no block frame?");
 
       PRInt32 lineFrameCount;
       nsIFrame *firstFrame;
       nsRect usedRect;
@@ -5331,17 +5331,17 @@ nsFrame::BreakWordBetweenPunctuation(con
 NS_IMETHODIMP
 nsFrame::CheckVisibility(nsPresContext* , PRInt32 , PRInt32 , PRBool , PRBool *, PRBool *)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 PRInt32
-nsFrame::GetLineNumber(nsIFrame *aFrame, nsIFrame** aContainingBlock)
+nsFrame::GetLineNumber(nsIFrame *aFrame, PRBool aLockScroll, nsIFrame** aContainingBlock)
 {
   NS_ASSERTION(aFrame, "null aFrame");
   nsFrameManager* frameManager = aFrame->PresContext()->FrameManager();
   nsIFrame *blockFrame = aFrame;
   nsIFrame *thisBlock;
   PRInt32   thisLine;
   nsCOMPtr<nsILineIteratorNavigator> it; 
   nsresult result = NS_ERROR_FAILURE;
@@ -5357,16 +5357,18 @@ nsFrame::GetLineNumber(nsIFrame *aFrame,
       }
       thisBlock = frameManager->GetPlaceholderFrameFor(thisBlock);
       if (!thisBlock)
         return -1;
     }  
     blockFrame = thisBlock->GetParent();
     result = NS_OK;
     if (blockFrame) {
+      if (aLockScroll && blockFrame->GetType() == nsGkAtoms::scrollFrame)
+        return -1;
       result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
     }
   }
   if (!blockFrame || !it)
     return -1;
 
   if (aContainingBlock)
     *aContainingBlock = blockFrame;
@@ -5391,17 +5393,17 @@ nsIFrame::GetFrameFromDirection(nsDirect
 
   // Find the prev/next selectable frame
   PRBool selectable = PR_FALSE;
   nsIFrame *traversedFrame = this;
   while (!selectable) {
     nsIFrame *blockFrame;
     nsCOMPtr<nsILineIteratorNavigator> it; 
     
-    PRInt32 thisLine = nsFrame::GetLineNumber(traversedFrame, &blockFrame);
+    PRInt32 thisLine = nsFrame::GetLineNumber(traversedFrame, aScrollViewStop, &blockFrame);
     if (thisLine < 0)
       return NS_ERROR_FAILURE;
     nsresult result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
     NS_ASSERTION(NS_SUCCEEDED(result) && it, "GetLineNumber() succeeded but no block frame?");
 
     PRBool atLineEdge;
     nsIFrame *firstFrame;
     nsIFrame *lastFrame;
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -558,18 +558,23 @@ protected:
   NS_IMETHOD DidSetStyleContext();
 
 public:
   //given a frame five me the first/last leaf available
   //XXX Robert O'Callahan wants to move these elsewhere
   static void GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
   static void GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
 
-  // return the line number of the aFrame, and (optionally) the containing block frame.
-  static PRInt32 GetLineNumber(nsIFrame *aFrame, nsIFrame** aContainingBlock = nsnull);
+  // Return the line number of the aFrame, and (optionally) the containing block
+  // frame.
+  // If aScrollLock is true, don't break outside scrollframes when looking for a
+  // containing block frame.
+  static PRInt32 GetLineNumber(nsIFrame *aFrame,
+                               PRBool aLockScroll,
+                               nsIFrame** aContainingBlock = nsnull);
 
 protected:
 
   // Test if we are selecting a table object:
   //  Most table/cell selection requires that Ctrl (Cmd on Mac) key is down 
   //   during a mouse click or drag. Exception is using Shift+click when
   //   already in "table/cell selection mode" to extend a block selection
   //  Get the parent content node and offset of the frame