2001-09-28 20:14:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2001-10-25 01:08:40 +00:00
|
|
|
// vim:cindent:ts=2:et:sw=2:
|
2001-09-28 20:14:13 +00:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
2004-04-18 14:30:37 +00:00
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
1998-04-13 20:24:54 +00:00
|
|
|
*
|
2004-04-18 14:30:37 +00:00
|
|
|
* 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/
|
1998-04-13 20:24:54 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* 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.
|
1998-04-13 20:24:54 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2004-04-18 14:30:37 +00:00
|
|
|
* The Initial Developer of the Original Code is
|
2001-09-28 20:14:13 +00:00
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 03:40:37 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Contributor(s):
|
2000-02-02 22:24:56 +00:00
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
2005-08-18 17:09:16 +00:00
|
|
|
* Uri Bernstein <uriber@gmail.com>
|
2005-12-07 23:08:39 +00:00
|
|
|
* Eli Friedman <sharparrow1@yahoo.com>
|
2006-12-20 03:52:34 +00:00
|
|
|
* Mats Palmgren <mats.palmgren@bredband.net>
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
2004-04-18 14:30:37 +00:00
|
|
|
* either of 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"),
|
2001-09-28 20:14:13 +00:00
|
|
|
* 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
|
2004-04-18 14:30:37 +00:00
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
2001-09-28 20:14:13 +00:00
|
|
|
* 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
|
2004-04-18 14:30:37 +00:00
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
2006-03-29 18:29:03 +00:00
|
|
|
|
|
|
|
/* base class of all rendering objects */
|
|
|
|
|
1999-02-12 17:45:58 +00:00
|
|
|
#include "nsCOMPtr.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsFrame.h"
|
1999-02-01 17:31:10 +00:00
|
|
|
#include "nsFrameList.h"
|
2009-08-31 18:25:35 +00:00
|
|
|
#include "nsPlaceholderFrame.h"
|
1998-10-09 23:46:02 +00:00
|
|
|
#include "nsLineLayout.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIContent.h"
|
2004-04-29 23:34:19 +00:00
|
|
|
#include "nsContentUtils.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIAtom.h"
|
|
|
|
#include "nsString.h"
|
2003-11-01 10:57:41 +00:00
|
|
|
#include "nsReadableUtils.h"
|
2003-02-22 00:32:13 +00:00
|
|
|
#include "nsStyleContext.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIView.h"
|
|
|
|
#include "nsIViewManager.h"
|
2009-09-13 13:13:16 +00:00
|
|
|
#include "nsIScrollableView.h"
|
2004-09-01 14:58:34 +00:00
|
|
|
#include "nsIScrollableFrame.h"
|
2004-07-31 23:15:21 +00:00
|
|
|
#include "nsPresContext.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsGUIEvent.h"
|
2000-12-30 19:22:22 +00:00
|
|
|
#include "nsIDOMEvent.h"
|
2006-05-03 17:02:37 +00:00
|
|
|
#include "nsPLDOMEvent.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsStyleConsts.h"
|
1998-05-08 16:33:07 +00:00
|
|
|
#include "nsIPresShell.h"
|
1998-05-20 16:24:13 +00:00
|
|
|
#include "prlog.h"
|
|
|
|
#include "prprf.h"
|
|
|
|
#include <stdarg.h>
|
2004-02-23 21:29:06 +00:00
|
|
|
#include "nsFrameManager.h"
|
2002-12-23 22:05:47 +00:00
|
|
|
#include "nsCSSRendering.h"
|
2005-03-07 00:34:44 +00:00
|
|
|
#include "nsLayoutUtils.h"
|
2001-08-17 03:13:07 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2001-04-01 01:01:33 +00:00
|
|
|
#include "nsIAccessible.h"
|
2001-08-17 03:13:07 +00:00
|
|
|
#endif
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
#include "nsIDOMText.h"
|
2002-04-01 04:27:50 +00:00
|
|
|
#include "nsIDOMHTMLAnchorElement.h"
|
|
|
|
#include "nsIDOMHTMLAreaElement.h"
|
|
|
|
#include "nsIDOMHTMLImageElement.h"
|
2003-04-07 14:28:51 +00:00
|
|
|
#include "nsIDOMHTMLHRElement.h"
|
2004-06-02 02:25:18 +00:00
|
|
|
#include "nsIDOMHTMLInputElement.h"
|
1998-05-08 18:33:42 +00:00
|
|
|
#include "nsIDeviceContext.h"
|
2004-09-28 18:40:50 +00:00
|
|
|
#include "nsIEditorDocShell.h"
|
1998-11-18 05:25:26 +00:00
|
|
|
#include "nsIEventStateManager.h"
|
2000-09-14 11:45:01 +00:00
|
|
|
#include "nsISelection.h"
|
2000-12-20 22:13:54 +00:00
|
|
|
#include "nsISelectionPrivate.h"
|
2006-04-26 02:01:07 +00:00
|
|
|
#include "nsFrameSelection.h"
|
1999-01-15 01:29:15 +00:00
|
|
|
#include "nsHTMLParts.h"
|
2007-01-30 00:06:41 +00:00
|
|
|
#include "nsGkAtoms.h"
|
2003-06-15 00:55:00 +00:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
|
|
|
#include "nsCSSPseudoElements.h"
|
2000-10-11 23:40:42 +00:00
|
|
|
#include "nsIHTMLContentSink.h"
|
2004-04-12 21:53:22 +00:00
|
|
|
#include "nsCSSFrameConstructor.h"
|
1998-05-08 18:33:42 +00:00
|
|
|
|
1999-02-10 18:55:25 +00:00
|
|
|
#include "nsFrameTraversal.h"
|
1999-03-25 06:43:38 +00:00
|
|
|
#include "nsStyleChangeList.h"
|
1999-09-20 21:47:37 +00:00
|
|
|
#include "nsIDOMRange.h"
|
2009-01-11 08:46:35 +00:00
|
|
|
#include "nsITableLayout.h" //selection necessity
|
2000-03-16 23:45:39 +00:00
|
|
|
#include "nsITableCellLayout.h"// "
|
2002-07-26 20:57:24 +00:00
|
|
|
#include "nsITextControlFrame.h"
|
2000-10-04 13:38:17 +00:00
|
|
|
#include "nsINameSpaceManager.h"
|
2001-12-07 14:51:12 +00:00
|
|
|
#include "nsIPercentHeightObserver.h"
|
2008-12-23 14:06:56 +00:00
|
|
|
#include "nsStyleStructInlines.h"
|
2000-05-11 04:25:43 +00:00
|
|
|
|
2006-07-12 11:22:18 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
#include "nsBidiPresUtils.h"
|
|
|
|
#endif
|
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
// For triple-click pref
|
|
|
|
#include "nsIServiceManager.h"
|
2002-09-11 03:03:49 +00:00
|
|
|
#include "imgIContainer.h"
|
2004-12-30 21:56:11 +00:00
|
|
|
#include "imgIRequest.h"
|
2002-09-11 03:03:49 +00:00
|
|
|
#include "nsILookAndFeel.h"
|
|
|
|
#include "nsLayoutCID.h"
|
|
|
|
#include "nsWidgetsCID.h" // for NS_LOOKANDFEEL_CID
|
2004-06-02 02:25:18 +00:00
|
|
|
#include "nsUnicharUtils.h"
|
2002-11-25 11:21:22 +00:00
|
|
|
#include "nsLayoutErrors.h"
|
2007-04-15 23:14:26 +00:00
|
|
|
#include "nsContentErrors.h"
|
2004-09-28 18:37:50 +00:00
|
|
|
#include "nsHTMLContainerFrame.h"
|
|
|
|
#include "nsBoxLayoutState.h"
|
2005-08-18 17:09:16 +00:00
|
|
|
#include "nsBlockFrame.h"
|
2006-01-26 02:29:17 +00:00
|
|
|
#include "nsDisplayList.h"
|
2002-09-11 03:03:49 +00:00
|
|
|
|
2008-09-11 00:24:16 +00:00
|
|
|
#ifdef MOZ_SVG
|
|
|
|
#include "nsSVGIntegrationUtils.h"
|
2008-10-01 00:51:05 +00:00
|
|
|
#include "nsSVGEffects.h"
|
2008-09-11 00:24:16 +00:00
|
|
|
#endif
|
|
|
|
|
2006-03-16 21:42:50 +00:00
|
|
|
#include "gfxContext.h"
|
|
|
|
|
2002-09-11 03:03:49 +00:00
|
|
|
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
2004-09-28 18:37:50 +00:00
|
|
|
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
1999-09-20 21:47:37 +00:00
|
|
|
|
2004-09-28 18:37:50 +00:00
|
|
|
// Struct containing cached metrics for box-wrapped frames.
|
|
|
|
struct nsBoxLayoutMetrics
|
|
|
|
{
|
|
|
|
nsSize mPrefSize;
|
|
|
|
nsSize mMinSize;
|
|
|
|
nsSize mMaxSize;
|
|
|
|
|
|
|
|
nsSize mBlockMinSize;
|
|
|
|
nsSize mBlockPrefSize;
|
|
|
|
nscoord mBlockAscent;
|
|
|
|
|
|
|
|
nscoord mFlex;
|
|
|
|
nscoord mAscent;
|
|
|
|
|
|
|
|
nsSize mLastSize;
|
|
|
|
};
|
1999-02-10 18:55:25 +00:00
|
|
|
|
2005-09-18 12:41:40 +00:00
|
|
|
struct nsContentAndOffset
|
|
|
|
{
|
|
|
|
nsIContent* mContent;
|
|
|
|
PRInt32 mOffset;
|
|
|
|
};
|
|
|
|
|
1998-07-18 18:18:20 +00:00
|
|
|
// Some Misc #defines
|
1998-07-22 22:01:46 +00:00
|
|
|
#define SELECTION_DEBUG 0
|
1998-07-18 18:18:20 +00:00
|
|
|
#define FORCE_SELECTION_UPDATE 1
|
|
|
|
#define CALC_DEBUG 0
|
|
|
|
|
1998-07-17 23:00:54 +00:00
|
|
|
|
1999-06-19 20:36:44 +00:00
|
|
|
#include "nsILineIterator.h"
|
2000-04-12 03:04:11 +00:00
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
//non Hack prototypes
|
1999-02-08 17:56:00 +00:00
|
|
|
#if 0
|
2004-07-31 23:15:21 +00:00
|
|
|
static void RefreshContentFrames(nsPresContext* aPresContext, nsIContent * aStartContent, nsIContent * aEndContent);
|
1999-02-08 17:56:00 +00:00
|
|
|
#endif
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
#include "prenv.h"
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2009-08-20 21:52:48 +00:00
|
|
|
// Formerly the nsIFrameDebug interface
|
1998-05-20 16:24:13 +00:00
|
|
|
|
1999-11-01 22:12:45 +00:00
|
|
|
#ifdef NS_DEBUG
|
1998-05-20 16:24:13 +00:00
|
|
|
static PRBool gShowFrameBorders = PR_FALSE;
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2009-08-20 21:52:48 +00:00
|
|
|
void nsFrame::ShowFrameBorders(PRBool aEnable)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
gShowFrameBorders = aEnable;
|
|
|
|
}
|
|
|
|
|
2009-08-20 21:52:48 +00:00
|
|
|
PRBool nsFrame::GetShowFrameBorders()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return gShowFrameBorders;
|
|
|
|
}
|
|
|
|
|
2000-02-03 02:49:58 +00:00
|
|
|
static PRBool gShowEventTargetFrameBorder = PR_FALSE;
|
|
|
|
|
2009-08-20 21:52:48 +00:00
|
|
|
void nsFrame::ShowEventTargetFrameBorder(PRBool aEnable)
|
2000-02-03 02:49:58 +00:00
|
|
|
{
|
|
|
|
gShowEventTargetFrameBorder = aEnable;
|
|
|
|
}
|
|
|
|
|
2009-08-20 21:52:48 +00:00
|
|
|
PRBool nsFrame::GetShowEventTargetFrameBorder()
|
2000-02-03 02:49:58 +00:00
|
|
|
{
|
|
|
|
return gShowEventTargetFrameBorder;
|
|
|
|
}
|
|
|
|
|
1998-05-20 16:24:13 +00:00
|
|
|
/**
|
|
|
|
* Note: the log module is created during library initialization which
|
|
|
|
* means that you cannot perform logging before then.
|
|
|
|
*/
|
1999-02-26 17:05:20 +00:00
|
|
|
static PRLogModuleInfo* gLogModule;
|
1998-05-20 16:24:13 +00:00
|
|
|
|
1999-09-21 07:51:52 +00:00
|
|
|
static PRLogModuleInfo* gStyleVerifyTreeLogModuleInfo;
|
|
|
|
|
|
|
|
static PRBool gStyleVerifyTreeEnable = PRBool(0x55);
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
PRBool
|
2009-08-20 21:52:48 +00:00
|
|
|
nsFrame::GetVerifyStyleTreeEnable()
|
1999-09-21 07:51:52 +00:00
|
|
|
{
|
|
|
|
if (gStyleVerifyTreeEnable == PRBool(0x55)) {
|
|
|
|
if (nsnull == gStyleVerifyTreeLogModuleInfo) {
|
|
|
|
gStyleVerifyTreeLogModuleInfo = PR_NewLogModule("styleverifytree");
|
|
|
|
gStyleVerifyTreeEnable = 0 != gStyleVerifyTreeLogModuleInfo->level;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return gStyleVerifyTreeEnable;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
void
|
2009-08-20 21:52:48 +00:00
|
|
|
nsFrame::SetVerifyStyleTreeEnable(PRBool aEnabled)
|
1999-09-21 07:51:52 +00:00
|
|
|
{
|
|
|
|
gStyleVerifyTreeEnable = aEnabled;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
PRLogModuleInfo*
|
2009-08-20 21:52:48 +00:00
|
|
|
nsFrame::GetLogModuleInfo()
|
1998-05-20 16:24:13 +00:00
|
|
|
{
|
1999-02-26 17:05:20 +00:00
|
|
|
if (nsnull == gLogModule) {
|
|
|
|
gLogModule = PR_NewLogModule("frame");
|
|
|
|
}
|
1998-05-20 16:24:13 +00:00
|
|
|
return gLogModule;
|
|
|
|
}
|
|
|
|
|
2007-03-08 01:48:25 +00:00
|
|
|
void
|
2009-08-20 21:52:48 +00:00
|
|
|
nsFrame::DumpFrameTree(nsIFrame* aFrame)
|
2007-03-08 01:48:25 +00:00
|
|
|
{
|
2007-03-30 21:11:41 +00:00
|
|
|
RootFrameList(aFrame->PresContext(), stdout, 0);
|
2007-03-08 01:48:25 +00:00
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
void
|
2009-08-20 21:52:48 +00:00
|
|
|
nsFrame::RootFrameList(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
|
2001-07-17 21:30:17 +00:00
|
|
|
{
|
2009-08-20 21:52:48 +00:00
|
|
|
if (!aPresContext || !out)
|
2001-07-17 21:30:17 +00:00
|
|
|
return;
|
|
|
|
|
2003-12-21 05:36:36 +00:00
|
|
|
nsIPresShell *shell = aPresContext->GetPresShell();
|
2009-08-20 21:52:48 +00:00
|
|
|
if (shell) {
|
2004-09-02 03:08:51 +00:00
|
|
|
nsIFrame* frame = shell->FrameManager()->GetRootFrame();
|
2009-08-20 21:52:48 +00:00
|
|
|
if(frame) {
|
|
|
|
frame->List(out, aIndent);
|
2001-07-17 21:30:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-07-17 22:02:11 +00:00
|
|
|
#endif
|
1998-05-20 16:24:13 +00:00
|
|
|
|
2008-05-28 13:39:41 +00:00
|
|
|
void
|
|
|
|
NS_MergeReflowStatusInto(nsReflowStatus* aPrimary, nsReflowStatus aSecondary)
|
|
|
|
{
|
|
|
|
*aPrimary |= aSecondary &
|
|
|
|
(NS_FRAME_NOT_COMPLETE | NS_FRAME_OVERFLOW_INCOMPLETE |
|
|
|
|
NS_FRAME_TRUNCATED | NS_FRAME_REFLOW_NEXTINFLOW);
|
|
|
|
if (*aPrimary & NS_FRAME_NOT_COMPLETE) {
|
|
|
|
*aPrimary &= ~NS_FRAME_OVERFLOW_INCOMPLETE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-18 06:38:15 +00:00
|
|
|
void
|
|
|
|
nsWeakFrame::Init(nsIFrame* aFrame)
|
|
|
|
{
|
2007-03-30 21:11:41 +00:00
|
|
|
Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nsnull);
|
2006-11-18 06:38:15 +00:00
|
|
|
mFrame = aFrame;
|
|
|
|
if (mFrame) {
|
2007-03-30 21:11:41 +00:00
|
|
|
nsIPresShell* shell = mFrame->PresContext()->GetPresShell();
|
2006-11-18 06:38:15 +00:00
|
|
|
NS_WARN_IF_FALSE(shell, "Null PresShell in nsWeakFrame!");
|
|
|
|
if (shell) {
|
|
|
|
shell->AddWeakFrame(this);
|
|
|
|
} else {
|
|
|
|
mFrame = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-01 20:40:54 +00:00
|
|
|
nsIFrame*
|
2006-03-26 21:30:36 +00:00
|
|
|
NS_NewEmptyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2006-03-26 21:30:36 +00:00
|
|
|
return new (aPresShell) nsFrame(aContext);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2006-03-26 21:30:36 +00:00
|
|
|
nsFrame::nsFrame(nsStyleContext* aContext)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-10-05 14:51:12 +00:00
|
|
|
MOZ_COUNT_CTOR(nsFrame);
|
|
|
|
|
2005-03-28 21:08:22 +00:00
|
|
|
mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY;
|
2006-03-26 21:30:36 +00:00
|
|
|
mStyleContext = aContext;
|
|
|
|
mStyleContext->AddRef();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsFrame::~nsFrame()
|
|
|
|
{
|
1999-10-05 14:51:12 +00:00
|
|
|
MOZ_COUNT_DTOR(nsFrame);
|
|
|
|
|
1998-08-04 18:19:51 +00:00
|
|
|
NS_IF_RELEASE(mContent);
|
2003-02-22 00:32:13 +00:00
|
|
|
if (mStyleContext)
|
|
|
|
mStyleContext->Release();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-09-12 16:49:24 +00:00
|
|
|
NS_IMPL_FRAMEARENA_HELPERS(nsFrame)
|
|
|
|
|
|
|
|
// Dummy operator delete. Will never be called, but must be defined
|
|
|
|
// to satisfy some C++ ABIs.
|
|
|
|
void
|
|
|
|
nsFrame::operator delete(void *, size_t)
|
|
|
|
{
|
|
|
|
NS_RUNTIMEABORT("nsFrame::operator delete should never be called");
|
|
|
|
}
|
|
|
|
|
2009-01-12 19:20:59 +00:00
|
|
|
NS_QUERYFRAME_HEAD(nsFrame)
|
|
|
|
NS_QUERYFRAME_ENTRY(nsIFrame)
|
2009-09-12 16:49:24 +00:00
|
|
|
NS_QUERYFRAME_TAIL_INHERITANCE_ROOT
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsIFrame
|
|
|
|
|
1998-12-03 06:31:43 +00:00
|
|
|
NS_IMETHODIMP
|
2006-03-09 18:55:21 +00:00
|
|
|
nsFrame::Init(nsIContent* aContent,
|
1999-01-14 05:16:23 +00:00
|
|
|
nsIFrame* aParent,
|
1999-02-25 03:27:57 +00:00
|
|
|
nsIFrame* aPrevInFlow)
|
1998-12-03 06:31:43 +00:00
|
|
|
{
|
2007-09-22 01:24:40 +00:00
|
|
|
NS_PRECONDITION(!mContent, "Double-initing a frame?");
|
2007-02-24 18:33:33 +00:00
|
|
|
NS_ASSERTION(IsFrameOfType(eDEBUGAllFrames) &&
|
|
|
|
!IsFrameOfType(eDEBUGNoFrames),
|
|
|
|
"IsFrameOfType implementation that doesn't call base class");
|
|
|
|
|
1998-12-03 06:31:43 +00:00
|
|
|
mContent = aContent;
|
1999-01-14 05:16:23 +00:00
|
|
|
mParent = aParent;
|
1999-10-23 23:19:14 +00:00
|
|
|
|
2005-03-23 03:21:04 +00:00
|
|
|
if (aContent) {
|
|
|
|
NS_ADDREF(aContent);
|
|
|
|
aContent->SetMayHaveFrame(PR_TRUE);
|
2005-03-23 03:07:10 +00:00
|
|
|
NS_ASSERTION(mContent->MayHaveFrame(), "SetMayHaveFrame failed?");
|
|
|
|
}
|
|
|
|
|
1999-10-23 23:19:14 +00:00
|
|
|
if (aPrevInFlow) {
|
|
|
|
// Make sure the general flags bits are the same
|
2003-06-27 18:13:48 +00:00
|
|
|
nsFrameState state = aPrevInFlow->GetStateBits();
|
2002-03-27 02:38:13 +00:00
|
|
|
|
|
|
|
// Make bits that are currently off (see constructor) the same:
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
mState |= state & (NS_FRAME_SELECTED_CONTENT |
|
2002-03-27 02:38:13 +00:00
|
|
|
NS_FRAME_INDEPENDENT_SELECTION |
|
2008-10-01 00:51:05 +00:00
|
|
|
NS_FRAME_IS_SPECIAL |
|
|
|
|
NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS);
|
1999-10-23 23:19:14 +00:00
|
|
|
}
|
2002-03-27 02:38:13 +00:00
|
|
|
if (mParent) {
|
2003-06-27 18:13:48 +00:00
|
|
|
nsFrameState state = mParent->GetStateBits();
|
2002-03-27 02:38:13 +00:00
|
|
|
|
|
|
|
// Make bits that are currently off (see constructor) the same:
|
|
|
|
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
|
|
|
|
NS_FRAME_GENERATED_CONTENT);
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
2008-09-13 09:42:11 +00:00
|
|
|
if (GetStyleDisplay()->HasTransform()) {
|
|
|
|
// The frame gets reconstructed if we toggle the -moz-transform
|
|
|
|
// property, so we can set this bit here and then ignore it.
|
2008-10-01 00:51:05 +00:00
|
|
|
mState |= NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS;
|
2008-09-13 09:42:11 +00:00
|
|
|
}
|
|
|
|
|
2008-10-26 10:11:34 +00:00
|
|
|
DidSetStyleContext(nsnull);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
if (IsBoxWrapped())
|
|
|
|
InitBoxMetrics(PR_FALSE);
|
|
|
|
|
2003-02-22 00:32:13 +00:00
|
|
|
return NS_OK;
|
1998-12-03 06:31:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-10 00:16:29 +00:00
|
|
|
NS_IMETHODIMP nsFrame::SetInitialChildList(nsIAtom* aListName,
|
2009-07-28 12:53:20 +00:00
|
|
|
nsFrameList& aChildList)
|
1998-09-10 19:32:14 +00:00
|
|
|
{
|
1998-11-10 06:05:32 +00:00
|
|
|
// XXX This shouldn't be getting called at all, but currently is for backwards
|
|
|
|
// compatility reasons...
|
|
|
|
#if 0
|
|
|
|
NS_ERROR("not a container");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
#else
|
2009-07-28 12:53:20 +00:00
|
|
|
NS_ASSERTION(aChildList.IsEmpty(), "not a container");
|
1998-09-10 19:32:14 +00:00
|
|
|
return NS_OK;
|
1998-11-10 06:05:32 +00:00
|
|
|
#endif
|
1998-09-10 19:32:14 +00:00
|
|
|
}
|
|
|
|
|
1999-01-15 01:29:15 +00:00
|
|
|
NS_IMETHODIMP
|
2005-02-07 01:58:25 +00:00
|
|
|
nsFrame::AppendFrames(nsIAtom* aListName,
|
2009-07-30 17:23:32 +00:00
|
|
|
nsFrameList& aFrameList)
|
1999-01-15 01:29:15 +00:00
|
|
|
{
|
1999-08-19 03:51:25 +00:00
|
|
|
NS_PRECONDITION(PR_FALSE, "not a container");
|
1999-01-15 01:29:15 +00:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2005-02-07 01:58:25 +00:00
|
|
|
nsFrame::InsertFrames(nsIAtom* aListName,
|
1999-01-15 01:29:15 +00:00
|
|
|
nsIFrame* aPrevFrame,
|
2009-07-30 17:23:32 +00:00
|
|
|
nsFrameList& aFrameList)
|
1999-01-15 01:29:15 +00:00
|
|
|
{
|
1999-08-19 03:51:25 +00:00
|
|
|
NS_PRECONDITION(PR_FALSE, "not a container");
|
1999-01-15 01:29:15 +00:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2005-02-07 01:58:25 +00:00
|
|
|
nsFrame::RemoveFrame(nsIAtom* aListName,
|
1999-01-15 01:29:15 +00:00
|
|
|
nsIFrame* aOldFrame)
|
|
|
|
{
|
1999-08-19 03:51:25 +00:00
|
|
|
NS_PRECONDITION(PR_FALSE, "not a container");
|
1999-01-15 01:29:15 +00:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2006-04-10 00:16:29 +00:00
|
|
|
void
|
|
|
|
nsFrame::Destroy()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2009-05-15 03:08:41 +00:00
|
|
|
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
|
|
|
|
"destroy called on frame while scripts not blocked");
|
|
|
|
|
2008-10-01 00:51:05 +00:00
|
|
|
#ifdef MOZ_SVG
|
|
|
|
nsSVGEffects::InvalidateDirectRenderingObservers(this);
|
|
|
|
#endif
|
|
|
|
|
1999-10-27 03:56:14 +00:00
|
|
|
// Get the view pointer now before the frame properties disappear
|
|
|
|
// when we call NotifyDestroyingFrame()
|
2003-06-27 18:13:48 +00:00
|
|
|
nsIView* view = GetView();
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext* presContext = PresContext();
|
2004-04-12 21:53:22 +00:00
|
|
|
|
2006-04-10 00:16:29 +00:00
|
|
|
nsIPresShell *shell = presContext->GetPresShell();
|
2009-05-13 21:35:02 +00:00
|
|
|
if (mState & NS_FRAME_OUT_OF_FLOW) {
|
|
|
|
nsPlaceholderFrame* placeholder =
|
|
|
|
shell->FrameManager()->GetPlaceholderFrameFor(this);
|
|
|
|
if (placeholder) {
|
|
|
|
shell->FrameManager()->UnregisterPlaceholderFrame(placeholder);
|
|
|
|
placeholder->SetOutOfFlowFrame(nsnull);
|
|
|
|
}
|
|
|
|
}
|
2005-03-23 03:35:08 +00:00
|
|
|
|
2006-05-06 21:42:49 +00:00
|
|
|
shell->NotifyDestroyingFrame(this);
|
1999-06-25 04:22:15 +00:00
|
|
|
|
2006-05-06 21:42:49 +00:00
|
|
|
if ((mState & NS_FRAME_EXTERNAL_REFERENCE) ||
|
|
|
|
(mState & NS_FRAME_SELECTED_CONTENT)) {
|
|
|
|
shell->ClearFrameRefs(this);
|
1998-11-19 00:43:36 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 02:52:54 +00:00
|
|
|
//XXX Why is this done in nsFrame instead of some frame class
|
1998-08-08 04:23:33 +00:00
|
|
|
// that actually loads images?
|
2006-04-10 00:16:29 +00:00
|
|
|
presContext->StopImagesFor(this);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1999-10-27 03:56:14 +00:00
|
|
|
if (view) {
|
|
|
|
// Break association between view and frame
|
|
|
|
view->SetClientData(nsnull);
|
2009-08-18 03:21:06 +00:00
|
|
|
|
1999-10-27 03:56:14 +00:00
|
|
|
// Destroy the view
|
|
|
|
view->Destroy();
|
1998-08-10 02:28:23 +00:00
|
|
|
}
|
|
|
|
|
2009-09-15 22:00:04 +00:00
|
|
|
// Must retrieve the object ID before calling destructors, so the
|
2009-09-12 16:49:24 +00:00
|
|
|
// vtable is still valid.
|
|
|
|
//
|
|
|
|
// Note to future tweakers: having the method that returns the
|
|
|
|
// object size call the destructor will not avoid an indirect call;
|
|
|
|
// the compiler cannot devirtualize the call to the destructor even
|
|
|
|
// if it's from a method defined in the same class.
|
|
|
|
|
2009-09-15 22:00:04 +00:00
|
|
|
nsQueryFrame::FrameIID id = GetFrameId();
|
2009-09-12 16:49:24 +00:00
|
|
|
this->~nsFrame();
|
1999-12-04 23:49:50 +00:00
|
|
|
|
2009-09-12 16:49:24 +00:00
|
|
|
// Now that we're totally cleaned out, we need to add ourselves to
|
|
|
|
// the presshell's recycler.
|
2009-09-15 22:00:04 +00:00
|
|
|
shell->FreeFrame(id, this);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1999-01-22 18:58:14 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const
|
|
|
|
{
|
|
|
|
aStart = 0;
|
|
|
|
aEnd = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-02-19 19:03:28 +00:00
|
|
|
static PRBool
|
|
|
|
EqualImages(imgIRequest *aOldImage, imgIRequest *aNewImage)
|
|
|
|
{
|
|
|
|
if (aOldImage == aNewImage)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
if (!aOldImage || !aNewImage)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> oldURI, newURI;
|
|
|
|
aOldImage->GetURI(getter_AddRefs(oldURI));
|
|
|
|
aNewImage->GetURI(getter_AddRefs(newURI));
|
|
|
|
PRBool equal;
|
|
|
|
return NS_SUCCEEDED(oldURI->Equals(newURI, &equal)) && equal;
|
|
|
|
}
|
|
|
|
|
1998-04-28 23:25:07 +00:00
|
|
|
// Subclass hook for style post processing
|
2008-10-13 22:03:28 +00:00
|
|
|
/* virtual */ void
|
2008-10-26 10:11:34 +00:00
|
|
|
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
1998-04-28 23:25:07 +00:00
|
|
|
{
|
2009-02-19 19:03:28 +00:00
|
|
|
if (aOldStyleContext) {
|
|
|
|
// If the old context had a background image image and new context
|
|
|
|
// does not have the same image, clear the image load notifier
|
|
|
|
// (which keeps the image loading, if it still is) for the frame.
|
|
|
|
// We want to do this conservatively because some frames paint their
|
|
|
|
// backgrounds from some other frame's style data, and we don't want
|
|
|
|
// to clear those notifiers unless we have to. (They'll be reset
|
|
|
|
// when we paint, although we could miss a notification in that
|
|
|
|
// interval.)
|
2009-02-20 05:29:21 +00:00
|
|
|
const nsStyleBackground *oldBG = aOldStyleContext->GetStyleBackground();
|
|
|
|
const nsStyleBackground *newBG = GetStyleBackground();
|
|
|
|
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, oldBG) {
|
2009-08-01 15:53:40 +00:00
|
|
|
if (i >= newBG->mImageCount ||
|
|
|
|
oldBG->mLayers[i].mImage != newBG->mLayers[i].mImage) {
|
2009-02-20 05:29:21 +00:00
|
|
|
// stop the image loading for the frame, the image has changed
|
|
|
|
PresContext()->SetImageLoaders(this,
|
|
|
|
nsPresContext::BACKGROUND_IMAGE, nsnull);
|
|
|
|
break;
|
|
|
|
}
|
2009-02-19 19:03:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
imgIRequest *oldBorderImage = aOldStyleContext
|
|
|
|
? aOldStyleContext->GetStyleBorder()->GetBorderImage()
|
|
|
|
: nsnull;
|
|
|
|
// For border-images, we can't be as conservative (we need to set the
|
|
|
|
// new loaders if there has been any change) since the CalcDifference
|
|
|
|
// call depended on the result of GetActualBorder() and that result
|
|
|
|
// depends on whether the image has loaded, start the image load now
|
|
|
|
// so that we'll get notified when it completes loading and can do a
|
|
|
|
// restyle. Otherwise, the image might finish loading from the
|
|
|
|
// network before we start listening to its notifications, and then
|
|
|
|
// we'll never know that it's finished loading. Likewise, we want to
|
|
|
|
// do this for freshly-created frames to prevent a similar race if the
|
|
|
|
// image loads between reflow (which can depend on whether the image
|
|
|
|
// is loaded) and paint. We also don't really care about any callers
|
|
|
|
// who try to paint borders with a different style context, because
|
|
|
|
// they won't have the correct size for the border either.
|
|
|
|
if (!EqualImages(oldBorderImage, GetStyleBorder()->GetBorderImage())) {
|
|
|
|
// stop and restart the image loading/notification
|
|
|
|
PresContext()->SetupBorderImageLoaders(this, GetStyleBorder());
|
2008-12-23 14:06:56 +00:00
|
|
|
}
|
2009-04-23 06:09:47 +00:00
|
|
|
|
|
|
|
// If the page contains markup that overrides text direction, and
|
|
|
|
// does not contain any characters that would activate the Unicode
|
|
|
|
// bidi algorithm, we need to call |SetBidiEnabled| on the pres
|
|
|
|
// context before reflow starts. See bug 115921.
|
|
|
|
if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
|
|
|
|
PresContext()->SetBidiEnabled();
|
|
|
|
}
|
1998-04-28 23:25:07 +00:00
|
|
|
}
|
|
|
|
|
2006-12-13 23:04:57 +00:00
|
|
|
/* virtual */ nsMargin
|
|
|
|
nsIFrame::GetUsedMargin() const
|
|
|
|
{
|
2008-01-30 04:53:46 +00:00
|
|
|
NS_ASSERTION(nsLayoutUtils::sDisableGetUsedXAssertions ||
|
|
|
|
!NS_SUBTREE_DIRTY(this) ||
|
2006-12-13 23:04:57 +00:00
|
|
|
(GetStateBits() & NS_FRAME_IN_REFLOW),
|
2008-01-30 04:53:46 +00:00
|
|
|
"cannot call GetUsedMargin on a dirty frame not currently "
|
|
|
|
"being reflowed");
|
2006-12-13 23:04:57 +00:00
|
|
|
|
|
|
|
nsMargin margin(0, 0, 0, 0);
|
|
|
|
if (!GetStyleMargin()->GetMargin(margin)) {
|
2007-07-08 07:08:04 +00:00
|
|
|
nsMargin *m = static_cast<nsMargin*>
|
|
|
|
(GetProperty(nsGkAtoms::usedMarginProperty));
|
2006-12-13 23:04:57 +00:00
|
|
|
NS_ASSERTION(m, "used margin property missing (out of memory?)");
|
|
|
|
if (m) {
|
|
|
|
margin = *m;
|
2004-03-10 04:43:59 +00:00
|
|
|
}
|
2001-02-07 09:57:26 +00:00
|
|
|
}
|
2006-12-13 23:04:57 +00:00
|
|
|
return margin;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsMargin
|
|
|
|
nsIFrame::GetUsedBorder() const
|
|
|
|
{
|
2008-01-30 04:53:46 +00:00
|
|
|
NS_ASSERTION(nsLayoutUtils::sDisableGetUsedXAssertions ||
|
|
|
|
!NS_SUBTREE_DIRTY(this) ||
|
2006-12-13 23:04:57 +00:00
|
|
|
(GetStateBits() & NS_FRAME_IN_REFLOW),
|
2008-01-30 04:53:46 +00:00
|
|
|
"cannot call GetUsedBorder on a dirty frame not currently "
|
|
|
|
"being reflowed");
|
2006-12-13 23:04:57 +00:00
|
|
|
|
2007-01-28 17:20:01 +00:00
|
|
|
// Theme methods don't use const-ness.
|
2007-07-08 07:08:04 +00:00
|
|
|
nsIFrame *mutable_this = const_cast<nsIFrame*>(this);
|
2007-01-28 17:20:01 +00:00
|
|
|
|
|
|
|
const nsStyleDisplay *disp = GetStyleDisplay();
|
|
|
|
if (mutable_this->IsThemed(disp)) {
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntMargin result;
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext *presContext = PresContext();
|
2007-01-28 17:20:01 +00:00
|
|
|
presContext->GetTheme()->GetWidgetBorder(presContext->DeviceContext(),
|
|
|
|
mutable_this, disp->mAppearance,
|
|
|
|
&result);
|
2009-01-15 03:27:09 +00:00
|
|
|
return nsMargin(presContext->DevPixelsToAppUnits(result.left),
|
|
|
|
presContext->DevPixelsToAppUnits(result.top),
|
|
|
|
presContext->DevPixelsToAppUnits(result.right),
|
|
|
|
presContext->DevPixelsToAppUnits(result.bottom));
|
2007-01-28 17:20:01 +00:00
|
|
|
}
|
|
|
|
|
2008-07-17 06:30:25 +00:00
|
|
|
return GetStyleBorder()->GetActualBorder();
|
2006-12-13 23:04:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsMargin
|
|
|
|
nsIFrame::GetUsedPadding() const
|
|
|
|
{
|
2008-01-30 04:53:46 +00:00
|
|
|
NS_ASSERTION(nsLayoutUtils::sDisableGetUsedXAssertions ||
|
|
|
|
!NS_SUBTREE_DIRTY(this) ||
|
2006-12-13 23:04:57 +00:00
|
|
|
(GetStateBits() & NS_FRAME_IN_REFLOW),
|
2008-01-30 04:53:46 +00:00
|
|
|
"cannot call GetUsedPadding on a dirty frame not currently "
|
|
|
|
"being reflowed");
|
2006-12-13 23:04:57 +00:00
|
|
|
|
|
|
|
nsMargin padding(0, 0, 0, 0);
|
2007-01-28 17:20:01 +00:00
|
|
|
|
|
|
|
// Theme methods don't use const-ness.
|
2007-07-08 07:08:04 +00:00
|
|
|
nsIFrame *mutable_this = const_cast<nsIFrame*>(this);
|
2007-01-28 17:20:01 +00:00
|
|
|
|
|
|
|
const nsStyleDisplay *disp = GetStyleDisplay();
|
|
|
|
if (mutable_this->IsThemed(disp)) {
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext *presContext = PresContext();
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntMargin widget;
|
2007-01-28 17:20:01 +00:00
|
|
|
if (presContext->GetTheme()->GetWidgetPadding(presContext->DeviceContext(),
|
|
|
|
mutable_this,
|
|
|
|
disp->mAppearance,
|
2009-01-15 03:27:09 +00:00
|
|
|
&widget)) {
|
|
|
|
padding.top = presContext->DevPixelsToAppUnits(widget.top);
|
|
|
|
padding.right = presContext->DevPixelsToAppUnits(widget.right);
|
|
|
|
padding.bottom = presContext->DevPixelsToAppUnits(widget.bottom);
|
|
|
|
padding.left = presContext->DevPixelsToAppUnits(widget.left);
|
2007-01-28 17:20:01 +00:00
|
|
|
return padding;
|
|
|
|
}
|
|
|
|
}
|
2006-12-13 23:04:57 +00:00
|
|
|
if (!GetStylePadding()->GetPadding(padding)) {
|
2007-07-08 07:08:04 +00:00
|
|
|
nsMargin *p = static_cast<nsMargin*>
|
|
|
|
(GetProperty(nsGkAtoms::usedPaddingProperty));
|
2006-12-13 23:04:57 +00:00
|
|
|
NS_ASSERTION(p, "used padding property missing (out of memory?)");
|
|
|
|
if (p) {
|
|
|
|
padding = *p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return padding;
|
2001-02-07 09:57:26 +00:00
|
|
|
}
|
|
|
|
|
2006-12-20 01:23:45 +00:00
|
|
|
void
|
|
|
|
nsIFrame::ApplySkipSides(nsMargin& aMargin) const
|
|
|
|
{
|
|
|
|
PRIntn skipSides = GetSkipSides();
|
|
|
|
if (skipSides & (1 << NS_SIDE_TOP))
|
|
|
|
aMargin.top = 0;
|
|
|
|
if (skipSides & (1 << NS_SIDE_RIGHT))
|
|
|
|
aMargin.right = 0;
|
|
|
|
if (skipSides & (1 << NS_SIDE_BOTTOM))
|
|
|
|
aMargin.bottom = 0;
|
|
|
|
if (skipSides & (1 << NS_SIDE_LEFT))
|
|
|
|
aMargin.left = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect
|
|
|
|
nsIFrame::GetMarginRect() const
|
|
|
|
{
|
|
|
|
nsMargin m(GetUsedMargin());
|
|
|
|
ApplySkipSides(m);
|
|
|
|
nsRect r(mRect);
|
|
|
|
r.Inflate(m);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect
|
|
|
|
nsIFrame::GetPaddingRect() const
|
|
|
|
{
|
|
|
|
nsMargin b(GetUsedBorder());
|
|
|
|
ApplySkipSides(b);
|
|
|
|
nsRect r(mRect);
|
|
|
|
r.Deflate(b);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-09-13 09:42:11 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::IsTransformed() const
|
|
|
|
{
|
2008-10-01 00:51:05 +00:00
|
|
|
return (mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
2008-09-13 09:42:11 +00:00
|
|
|
GetStyleDisplay()->HasTransform();
|
|
|
|
}
|
|
|
|
|
2006-12-20 01:23:45 +00:00
|
|
|
nsRect
|
|
|
|
nsIFrame::GetContentRect() const
|
|
|
|
{
|
|
|
|
nsMargin bp(GetUsedBorderAndPadding());
|
|
|
|
ApplySkipSides(bp);
|
|
|
|
nsRect r(mRect);
|
|
|
|
r.Deflate(bp);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2003-02-22 00:32:13 +00:00
|
|
|
nsStyleContext*
|
|
|
|
nsFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
|
1999-09-03 23:35:14 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aIndex >= 0, "invalid index number");
|
2003-02-22 00:32:13 +00:00
|
|
|
return nsnull;
|
1999-09-03 23:35:14 +00:00
|
|
|
}
|
|
|
|
|
2003-02-22 00:32:13 +00:00
|
|
|
void
|
1999-09-03 23:35:14 +00:00
|
|
|
nsFrame::SetAdditionalStyleContext(PRInt32 aIndex,
|
2003-02-22 00:32:13 +00:00
|
|
|
nsStyleContext* aStyleContext)
|
1999-09-03 23:35:14 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aIndex >= 0, "invalid index number");
|
|
|
|
}
|
|
|
|
|
2009-04-05 23:35:53 +00:00
|
|
|
nsCSSShadowArray*
|
|
|
|
nsIFrame::GetEffectiveBoxShadows()
|
|
|
|
{
|
|
|
|
nsCSSShadowArray* shadows = GetStyleBorder()->mBoxShadow;
|
|
|
|
if (!shadows ||
|
|
|
|
(IsThemed() && GetContent() &&
|
|
|
|
!nsContentUtils::IsChromeDoc(GetContent()->GetCurrentDoc())))
|
|
|
|
return nsnull;
|
|
|
|
return shadows;
|
|
|
|
}
|
|
|
|
|
2007-01-23 04:06:56 +00:00
|
|
|
nscoord
|
|
|
|
nsFrame::GetBaseline() const
|
|
|
|
{
|
2007-05-06 19:16:51 +00:00
|
|
|
NS_ASSERTION(!NS_SUBTREE_DIRTY(this),
|
2007-01-23 04:06:56 +00:00
|
|
|
"frame must not be dirty");
|
|
|
|
// Default to the bottom margin edge, per CSS2.1's definition of the
|
|
|
|
// 'baseline' value of 'vertical-align'.
|
|
|
|
return mRect.height + GetUsedMargin().bottom;
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Child frame enumeration
|
|
|
|
|
2004-01-09 14:20:53 +00:00
|
|
|
nsIAtom*
|
|
|
|
nsFrame::GetAdditionalChildListName(PRInt32 aIndex) const
|
1998-11-09 19:59:33 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aIndex >= 0, "invalid index number");
|
2004-01-09 14:20:53 +00:00
|
|
|
return nsnull;
|
1998-11-09 19:59:33 +00:00
|
|
|
}
|
|
|
|
|
2009-07-28 12:51:09 +00:00
|
|
|
nsFrameList
|
|
|
|
nsFrame::GetChildList(nsIAtom* aListName) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2009-07-28 12:51:09 +00:00
|
|
|
return nsFrameList::EmptyList();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2005-03-07 00:34:44 +00:00
|
|
|
static nsIFrame*
|
2009-09-13 13:13:16 +00:00
|
|
|
GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
nsIPresShell* shell = aPresContext->GetPresShell();
|
|
|
|
if (shell) {
|
|
|
|
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
|
|
|
|
if (capturingContent) {
|
|
|
|
nsIFrame* activeFrame = shell->GetPrimaryFrameFor(capturingContent);
|
|
|
|
return activeFrame ? activeFrame : aFrame;
|
2005-03-07 00:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-13 13:13:16 +00:00
|
|
|
|
2005-03-07 00:34:44 +00:00
|
|
|
return aFrame;
|
|
|
|
}
|
|
|
|
|
2000-04-30 18:56:26 +00:00
|
|
|
PRInt16
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn)
|
1998-08-03 23:39:16 +00:00
|
|
|
{
|
2000-08-05 04:41:33 +00:00
|
|
|
PRInt16 selType = nsISelectionController::SELECTION_OFF;
|
1998-08-03 23:39:16 +00:00
|
|
|
|
2000-05-04 08:35:42 +00:00
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
2000-08-05 04:41:33 +00:00
|
|
|
nsresult result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
2000-05-04 08:35:42 +00:00
|
|
|
if (NS_SUCCEEDED(result) && selCon) {
|
2000-08-05 04:41:33 +00:00
|
|
|
result = selCon->GetDisplaySelection(&selType);
|
|
|
|
if (NS_SUCCEEDED(result) && (selType != nsISelectionController::SELECTION_OFF)) {
|
|
|
|
// Check whether style allows selection.
|
|
|
|
PRBool selectable;
|
2000-08-08 23:48:42 +00:00
|
|
|
IsSelectable(&selectable, nsnull);
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable) {
|
|
|
|
selType = nsISelectionController::SELECTION_OFF;
|
|
|
|
isOkToTurnOn = PR_FALSE;
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-05 04:41:33 +00:00
|
|
|
if (isOkToTurnOn && (selType == nsISelectionController::SELECTION_OFF)) {
|
2000-05-04 08:35:42 +00:00
|
|
|
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
2000-08-05 04:41:33 +00:00
|
|
|
selType = nsISelectionController::SELECTION_ON;
|
1998-08-03 23:39:16 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-05 04:41:33 +00:00
|
|
|
return selType;
|
1998-07-27 18:05:35 +00:00
|
|
|
}
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
class nsDisplaySelectionOverlay : public nsDisplayItem {
|
|
|
|
public:
|
|
|
|
nsDisplaySelectionOverlay(nsFrame* aFrame, PRInt16 aSelectionValue)
|
2006-03-14 20:43:18 +00:00
|
|
|
: nsDisplayItem(aFrame), mSelectionValue(aSelectionValue) {
|
2006-01-29 18:48:58 +00:00
|
|
|
MOZ_COUNT_CTOR(nsDisplaySelectionOverlay);
|
|
|
|
}
|
|
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
|
|
virtual ~nsDisplaySelectionOverlay() {
|
|
|
|
MOZ_COUNT_DTOR(nsDisplaySelectionOverlay);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
|
|
|
|
const nsRect& aDirtyRect);
|
|
|
|
NS_DISPLAY_DECL_NAME("SelectionOverlay")
|
|
|
|
private:
|
|
|
|
PRInt16 mSelectionValue;
|
|
|
|
};
|
2000-04-25 04:43:11 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
void nsDisplaySelectionOverlay::Paint(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
|
|
|
|
{
|
2006-03-16 21:42:50 +00:00
|
|
|
nscolor color = NS_RGB(255, 255, 255);
|
|
|
|
|
2006-06-17 01:05:26 +00:00
|
|
|
nsILookAndFeel::nsColorID colorID;
|
2006-03-16 21:42:50 +00:00
|
|
|
nsresult result;
|
2006-06-17 01:05:26 +00:00
|
|
|
if (mSelectionValue == nsISelectionController::SELECTION_ON) {
|
|
|
|
colorID = nsILookAndFeel::eColor_TextSelectBackground;
|
|
|
|
} else if (mSelectionValue == nsISelectionController::SELECTION_ATTENTION) {
|
|
|
|
colorID = nsILookAndFeel::eColor_TextSelectBackgroundAttention;
|
|
|
|
} else {
|
|
|
|
colorID = nsILookAndFeel::eColor_TextSelectBackgroundDisabled;
|
|
|
|
}
|
2006-03-16 21:42:50 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsILookAndFeel> look;
|
2006-06-17 01:05:26 +00:00
|
|
|
look = do_GetService(kLookAndFeelCID, &result);
|
2006-03-16 21:42:50 +00:00
|
|
|
if (NS_SUCCEEDED(result) && look)
|
2006-06-17 01:05:26 +00:00
|
|
|
look->GetColor(colorID, color);
|
2006-03-16 21:42:50 +00:00
|
|
|
|
|
|
|
gfxRGBA c(color);
|
|
|
|
c.a = .5;
|
|
|
|
|
2008-06-03 22:25:31 +00:00
|
|
|
gfxContext *ctx = aCtx->ThebesContext();
|
2006-03-16 21:42:50 +00:00
|
|
|
ctx->SetColor(c);
|
|
|
|
|
|
|
|
nsRect rect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
|
|
|
|
rect.IntersectRect(rect, aDirtyRect);
|
2009-05-08 02:31:04 +00:00
|
|
|
nsIntRect pxRect = rect.ToOutsidePixels(mFrame->PresContext()->AppUnitsPerDevPixel());
|
2007-03-24 09:21:35 +00:00
|
|
|
ctx->NewPath();
|
2009-01-15 03:27:09 +00:00
|
|
|
ctx->Rectangle(gfxRect(pxRect.x, pxRect.y, pxRect.width, pxRect.height), PR_TRUE);
|
2006-03-16 21:42:50 +00:00
|
|
|
ctx->Fill();
|
1999-04-10 17:32:22 +00:00
|
|
|
}
|
|
|
|
|
2002-08-06 23:56:50 +00:00
|
|
|
/********************************************************
|
|
|
|
* Refreshes each content's frame
|
|
|
|
*********************************************************/
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
nsresult
|
|
|
|
nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists,
|
|
|
|
PRUint16 aContentType)
|
1998-12-18 15:54:23 +00:00
|
|
|
{
|
2006-01-26 02:29:17 +00:00
|
|
|
//check frame selection state
|
|
|
|
if ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) != NS_FRAME_SELECTED_CONTENT)
|
|
|
|
return NS_OK;
|
|
|
|
if (!IsVisibleForPainting(aBuilder))
|
|
|
|
return NS_OK;
|
|
|
|
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext* presContext = PresContext();
|
2006-01-26 02:29:17 +00:00
|
|
|
nsIPresShell *shell = presContext->PresShell();
|
|
|
|
if (!shell)
|
2000-08-08 23:48:42 +00:00
|
|
|
return NS_OK;
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
PRInt16 displaySelection;
|
|
|
|
nsresult rv = shell->GetSelectionFlags(&displaySelection);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
if (!(displaySelection & aContentType))
|
|
|
|
return NS_OK;
|
1999-05-17 00:21:18 +00:00
|
|
|
|
2007-11-22 20:47:33 +00:00
|
|
|
const nsFrameSelection* frameSelection = GetConstFrameSelection();
|
2006-04-26 02:01:07 +00:00
|
|
|
PRInt16 selectionValue = frameSelection->GetDisplaySelection();
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
if (selectionValue <= nsISelectionController::SELECTION_HIDDEN)
|
|
|
|
return NS_OK; // selection is hidden or off
|
1999-07-15 18:19:03 +00:00
|
|
|
|
2003-09-27 04:18:26 +00:00
|
|
|
nsIContent *newContent = mContent->GetParent();
|
2000-05-11 04:25:43 +00:00
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
//check to see if we are anonymous content
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 offset = 0;
|
2003-07-28 21:25:13 +00:00
|
|
|
if (newContent) {
|
|
|
|
// XXXbz there has GOT to be a better way of determining this!
|
2003-09-27 04:18:26 +00:00
|
|
|
offset = newContent->IndexOf(mContent);
|
2000-05-11 04:25:43 +00:00
|
|
|
}
|
1999-04-26 04:02:04 +00:00
|
|
|
|
2000-05-11 04:25:43 +00:00
|
|
|
SelectionDetails *details;
|
2006-02-21 00:49:04 +00:00
|
|
|
//look up to see what selection(s) are on this frame
|
2006-04-26 02:01:07 +00:00
|
|
|
details = frameSelection->LookUpSelection(newContent, offset, 1, PR_FALSE);
|
2006-01-26 02:29:17 +00:00
|
|
|
// XXX is the above really necessary? We don't actually DO anything
|
|
|
|
// with the details other than test that they're non-null
|
2006-04-26 02:01:07 +00:00
|
|
|
if (!details)
|
|
|
|
return NS_OK;
|
2000-08-08 23:48:42 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
while (details) {
|
|
|
|
SelectionDetails *next = details->mNext;
|
1999-07-15 18:19:03 +00:00
|
|
|
delete details;
|
2006-01-26 02:29:17 +00:00
|
|
|
details = next;
|
1998-05-08 18:33:42 +00:00
|
|
|
}
|
2006-01-26 02:29:17 +00:00
|
|
|
|
|
|
|
return aLists.Content()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplaySelectionOverlay(this, selectionValue));
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
nsresult
|
|
|
|
nsFrame::DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists)
|
|
|
|
{
|
|
|
|
if (GetStyleOutline()->GetOutlineStyle() == NS_STYLE_BORDER_STYLE_NONE)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
return aLists.Outlines()->AppendNewToTop(new (aBuilder) nsDisplayOutline(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFrame::DisplayOutline(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists)
|
|
|
|
{
|
|
|
|
if (!IsVisibleForPainting(aBuilder))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
return DisplayOutlineUnconditional(aBuilder, aLists);
|
|
|
|
}
|
|
|
|
|
2006-04-17 23:16:46 +00:00
|
|
|
nsresult
|
|
|
|
nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsRect& aDirtyRect, const nsDisplayListSet& aLists)
|
|
|
|
{
|
|
|
|
if (!IsVisibleForPainting(aBuilder))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
return aLists.Content()->AppendNewToTop(
|
|
|
|
new (aBuilder) nsDisplayCaret(this, aBuilder->GetCaret()));
|
|
|
|
}
|
|
|
|
|
2006-09-19 21:46:01 +00:00
|
|
|
PRBool
|
2007-10-12 08:30:54 +00:00
|
|
|
nsFrame::HasBorder() const
|
2006-09-19 21:46:01 +00:00
|
|
|
{
|
2009-02-20 04:13:47 +00:00
|
|
|
// Border images contribute to the background of the content area
|
|
|
|
// even if there's no border proper.
|
|
|
|
return (GetUsedBorder() != nsMargin(0,0,0,0) ||
|
|
|
|
GetStyleBorder()->IsBorderImageLoaded());
|
2006-09-19 21:46:01 +00:00
|
|
|
}
|
|
|
|
|
2009-07-22 00:44:51 +00:00
|
|
|
nsresult
|
|
|
|
nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists,
|
|
|
|
PRBool aForceBackground)
|
|
|
|
{
|
|
|
|
// Here we don't try to detect background propagation. Frames that might
|
|
|
|
// receive a propagated background should just set aForceBackground to
|
|
|
|
// PR_TRUE.
|
|
|
|
if (aBuilder->IsForEventDelivery() || aForceBackground ||
|
|
|
|
!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance) {
|
|
|
|
return aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplayBackground(this));
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
nsresult
|
|
|
|
nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists,
|
|
|
|
PRBool aForceBackground)
|
2002-12-23 22:05:47 +00:00
|
|
|
{
|
|
|
|
// The visibility check belongs here since child elements have the
|
|
|
|
// opportunity to override the visibility property and display even if
|
|
|
|
// their parent is hidden.
|
2006-01-26 02:29:17 +00:00
|
|
|
if (!IsVisibleForPainting(aBuilder))
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-04-05 23:35:53 +00:00
|
|
|
PRBool hasBoxShadow = GetEffectiveBoxShadows() != nsnull;
|
2009-02-10 08:45:13 +00:00
|
|
|
if (hasBoxShadow) {
|
2008-07-08 00:57:47 +00:00
|
|
|
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
2009-02-10 08:45:13 +00:00
|
|
|
nsDisplayBoxShadowOuter(this));
|
2008-07-08 00:57:47 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
2009-07-22 00:44:51 +00:00
|
|
|
nsresult rv =
|
|
|
|
DisplayBackgroundUnconditional(aBuilder, aLists, aForceBackground);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2009-02-10 08:45:13 +00:00
|
|
|
|
|
|
|
if (hasBoxShadow) {
|
2009-07-22 00:44:51 +00:00
|
|
|
rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
2009-02-10 08:45:13 +00:00
|
|
|
nsDisplayBoxShadowInner(this));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2006-01-26 02:29:17 +00:00
|
|
|
|
|
|
|
if (HasBorder()) {
|
2009-07-22 00:44:51 +00:00
|
|
|
rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
2006-01-26 02:29:17 +00:00
|
|
|
nsDisplayBorder(this));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DisplayOutlineUnconditional(aBuilder, aLists);
|
|
|
|
}
|
|
|
|
|
2006-06-08 01:11:43 +00:00
|
|
|
PRBool
|
2007-04-11 05:04:09 +00:00
|
|
|
nsIFrame::GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
|
|
|
|
const nsSize& aSize)
|
2006-06-08 01:11:43 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aRect, "Must have aRect out parameter");
|
|
|
|
|
|
|
|
if (!aDisp->IsAbsolutelyPositioned() ||
|
|
|
|
!(aDisp->mClipFlags & NS_STYLE_CLIP_RECT))
|
|
|
|
return PR_FALSE;
|
|
|
|
|
2007-03-29 01:31:26 +00:00
|
|
|
*aRect = aDisp->mClip;
|
|
|
|
if (NS_STYLE_CLIP_RIGHT_AUTO & aDisp->mClipFlags) {
|
2007-04-11 05:04:09 +00:00
|
|
|
aRect->width = aSize.width - aRect->x;
|
2006-06-08 01:11:43 +00:00
|
|
|
}
|
2007-03-29 01:31:26 +00:00
|
|
|
if (NS_STYLE_CLIP_BOTTOM_AUTO & aDisp->mClipFlags) {
|
2007-04-11 05:04:09 +00:00
|
|
|
aRect->height = aSize.height - aRect->y;
|
2006-06-08 01:11:43 +00:00
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
static PRBool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsStyleDisplay* aDisp, nsIFrame* aFrame,
|
|
|
|
nsRect* aRect) {
|
2007-04-11 05:04:09 +00:00
|
|
|
if (!aFrame->GetAbsPosClipRect(aDisp, aRect, aFrame->GetSize()))
|
2006-01-26 02:29:17 +00:00
|
|
|
return PR_FALSE;
|
2007-04-11 05:04:09 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
// A moving frame should not be allowed to clip a non-moving frame.
|
|
|
|
// Abs-pos clipping always clips frames below it in the frame tree, except
|
|
|
|
// for when an abs-pos frame clips a fixed-pos frame. So when fixed-pos
|
|
|
|
// elements are present we do not allow a moving abs-pos frame with
|
|
|
|
// an out-of-flow descendant (which could be a fixed frame) child to clip
|
|
|
|
// anything. It's OK to not clip anything, even the moving children ...
|
|
|
|
// all that could happen is that we get unnecessarily conservative results
|
|
|
|
// for nsLayoutUtils::ComputeRepaintRegionForCopy ... but this is a rare
|
|
|
|
// situation.
|
|
|
|
if (aBuilder->HasMovingFrames() &&
|
2007-03-30 21:11:41 +00:00
|
|
|
aFrame->PresContext()->FrameManager()->GetRootFrame()->
|
2006-12-26 17:47:52 +00:00
|
|
|
GetFirstChild(nsGkAtoms::fixedList) &&
|
2006-01-26 02:29:17 +00:00
|
|
|
aBuilder->IsMovingFrame(aFrame))
|
|
|
|
return PR_FALSE;
|
2006-06-08 01:11:43 +00:00
|
|
|
|
2006-06-15 03:25:33 +00:00
|
|
|
*aRect += aBuilder->ToReferenceFrame(aFrame);
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns PR_TRUE if aFrame is overflow:hidden and we should interpret
|
|
|
|
* that as -moz-hidden-unscrollable.
|
|
|
|
*/
|
|
|
|
static PRBool ApplyOverflowHiddenClipping(nsIFrame* aFrame,
|
|
|
|
const nsStyleDisplay* aDisp)
|
|
|
|
{
|
|
|
|
if (aDisp->mOverflowX != NS_STYLE_OVERFLOW_HIDDEN)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
nsIAtom* type = aFrame->GetType();
|
|
|
|
// REVIEW: these are the frame types that call IsTableClip and set up
|
|
|
|
// clipping. Actually there were also table rows and the inner table frame
|
|
|
|
// doing this, but 'overflow' isn't applicable to them according to
|
|
|
|
// CSS 2.1 so I removed them. Also, we used to clip at tableOuterFrame
|
|
|
|
// but we should actually clip at tableFrame (as per discussion with Hixie and
|
|
|
|
// bz).
|
2006-12-26 17:47:52 +00:00
|
|
|
return type == nsGkAtoms::tableFrame ||
|
|
|
|
type == nsGkAtoms::tableCellFrame ||
|
|
|
|
type == nsGkAtoms::bcTableCellFrame;
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static PRBool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
const nsStyleDisplay* aDisp, nsRect* aRect) {
|
|
|
|
// REVIEW: from nsContainerFrame.cpp SyncFrameViewGeometryDependentProperties,
|
|
|
|
// except that that function used the border-edge for
|
|
|
|
// -moz-hidden-unscrollable which I don't think is correct... Also I've
|
|
|
|
// changed -moz-hidden-unscrollable to apply to any kind of frame.
|
|
|
|
|
|
|
|
// Only -moz-hidden-unscrollable is handled here (and 'hidden' for table
|
|
|
|
// frames). Other overflow clipping is applied by nsHTML/XULScrollFrame.
|
|
|
|
if (!ApplyOverflowHiddenClipping(aFrame, aDisp)) {
|
|
|
|
PRBool clip = aDisp->mOverflowX == NS_STYLE_OVERFLOW_CLIP;
|
|
|
|
if (!clip)
|
|
|
|
return PR_FALSE;
|
|
|
|
// We allow -moz-hidden-unscrollable to apply to any kind of frame. This
|
|
|
|
// is required by comboboxes which make their display text (an inline frame)
|
|
|
|
// have clipping.
|
|
|
|
}
|
|
|
|
|
2007-09-25 00:47:05 +00:00
|
|
|
*aRect = aFrame->GetPaddingRect() - aFrame->GetPosition() +
|
|
|
|
aBuilder->ToReferenceFrame(aFrame);
|
2006-01-26 02:29:17 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
class nsOverflowClipWrapper : public nsDisplayWrapper
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Create a wrapper to apply overflow clipping for aContainer.
|
|
|
|
* @param aClipBorderBackground set to PR_TRUE to clip the BorderBackground()
|
|
|
|
* list, otherwise it will not be clipped
|
|
|
|
* @param aClipAll set to PR_TRUE to clip all descendants, even those for
|
|
|
|
* which we aren't the containing block
|
|
|
|
*/
|
|
|
|
nsOverflowClipWrapper(nsIFrame* aContainer, const nsRect& aRect,
|
|
|
|
PRBool aClipBorderBackground, PRBool aClipAll)
|
|
|
|
: mContainer(aContainer), mRect(aRect),
|
|
|
|
mClipBorderBackground(aClipBorderBackground), mClipAll(aClipAll) {}
|
|
|
|
virtual PRBool WrapBorderBackground() { return mClipBorderBackground; }
|
|
|
|
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsIFrame* aFrame, nsDisplayList* aList) {
|
|
|
|
// We are not a stacking context root. There is no valid underlying
|
|
|
|
// frame for the whole list. These items are all in-flow descendants so
|
|
|
|
// we can safely just clip them.
|
2008-04-18 09:21:21 +00:00
|
|
|
return new (aBuilder) nsDisplayClip(nsnull, mContainer, aList, mRect);
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
|
|
|
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsDisplayItem* aItem) {
|
|
|
|
nsIFrame* f = aItem->GetUnderlyingFrame();
|
|
|
|
if (mClipAll || nsLayoutUtils::IsProperAncestorFrame(mContainer, f, nsnull))
|
2008-04-18 09:21:21 +00:00
|
|
|
return new (aBuilder) nsDisplayClip(f, mContainer, aItem, mRect);
|
2006-01-26 02:29:17 +00:00
|
|
|
return aItem;
|
|
|
|
}
|
|
|
|
protected:
|
|
|
|
nsIFrame* mContainer;
|
|
|
|
nsRect mRect;
|
|
|
|
PRPackedBool mClipBorderBackground;
|
|
|
|
PRPackedBool mClipAll;
|
|
|
|
};
|
|
|
|
|
|
|
|
class nsAbsPosClipWrapper : public nsDisplayWrapper
|
|
|
|
{
|
|
|
|
public:
|
2008-04-18 09:21:21 +00:00
|
|
|
nsAbsPosClipWrapper(nsIFrame* aContainer, const nsRect& aRect)
|
|
|
|
: mContainer(aContainer), mRect(aRect) {}
|
2006-01-26 02:29:17 +00:00
|
|
|
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsIFrame* aFrame, nsDisplayList* aList) {
|
|
|
|
// We are not a stacking context root. There is no valid underlying
|
|
|
|
// frame for the whole list.
|
2008-04-18 09:21:21 +00:00
|
|
|
return new (aBuilder) nsDisplayClip(nsnull, mContainer, aList, mRect);
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
|
|
|
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsDisplayItem* aItem) {
|
2008-04-18 09:21:21 +00:00
|
|
|
return new (aBuilder) nsDisplayClip(aItem->GetUnderlyingFrame(),
|
|
|
|
mContainer, aItem, mRect);
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
|
|
|
protected:
|
2008-04-18 09:21:21 +00:00
|
|
|
nsIFrame* mContainer;
|
|
|
|
nsRect mRect;
|
2006-01-26 02:29:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsIFrame::OverflowClip(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aFromSet,
|
|
|
|
const nsDisplayListSet& aToSet,
|
|
|
|
const nsRect& aClipRect,
|
|
|
|
PRBool aClipBorderBackground,
|
|
|
|
PRBool aClipAll)
|
|
|
|
{
|
|
|
|
nsOverflowClipWrapper wrapper(this, aClipRect, aClipBorderBackground, aClipAll);
|
|
|
|
return wrapper.WrapLists(aBuilder, this, aFromSet, aToSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsIFrame::Clip(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aFromSet,
|
|
|
|
const nsDisplayListSet& aToSet,
|
|
|
|
const nsRect& aClipRect)
|
|
|
|
{
|
2008-04-18 09:21:21 +00:00
|
|
|
nsAbsPosClipWrapper wrapper(this, aClipRect);
|
2006-01-26 02:29:17 +00:00
|
|
|
return wrapper.WrapLists(aBuilder, this, aFromSet, aToSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsresult
|
|
|
|
BuildDisplayListWithOverflowClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
|
|
|
const nsRect& aDirtyRect, const nsDisplayListSet& aSet,
|
|
|
|
const nsRect& aClipRect)
|
|
|
|
{
|
|
|
|
nsDisplayListCollection set;
|
|
|
|
nsresult rv = aFrame->BuildDisplayList(aBuilder, aDirtyRect, set);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2006-04-17 23:16:46 +00:00
|
|
|
rv = aBuilder->DisplayCaret(aFrame, aDirtyRect, aSet);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2006-01-26 02:29:17 +00:00
|
|
|
|
|
|
|
return aFrame->OverflowClip(aBuilder, set, aSet, aClipRect);
|
|
|
|
}
|
|
|
|
|
2007-02-20 20:22:19 +00:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
static void PaintDebugBorder(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
|
|
|
const nsRect& aDirtyRect, nsPoint aPt) {
|
|
|
|
nsRect r(aPt, aFrame->GetSize());
|
|
|
|
if (aFrame->HasView()) {
|
|
|
|
aCtx->SetColor(NS_RGB(0,0,255));
|
|
|
|
} else {
|
|
|
|
aCtx->SetColor(NS_RGB(255,0,0));
|
|
|
|
}
|
|
|
|
aCtx->DrawRect(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void PaintEventTargetBorder(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
|
|
|
const nsRect& aDirtyRect, nsPoint aPt) {
|
|
|
|
nsRect r(aPt, aFrame->GetSize());
|
|
|
|
aCtx->SetColor(NS_RGB(128,0,128));
|
|
|
|
aCtx->DrawRect(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
DisplayDebugBorders(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
|
|
|
const nsDisplayListSet& aLists) {
|
|
|
|
// Draw a border around the child
|
|
|
|
// REVIEW: From nsContainerFrame::PaintChild
|
2009-08-20 21:52:48 +00:00
|
|
|
if (nsFrame::GetShowFrameBorders() && !aFrame->GetRect().IsEmpty()) {
|
2007-02-20 20:22:19 +00:00
|
|
|
aLists.Outlines()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplayGeneric(aFrame, PaintDebugBorder, "DebugBorder"));
|
|
|
|
}
|
|
|
|
// Draw a border around the current event target
|
2009-08-20 21:52:48 +00:00
|
|
|
if (nsFrame::GetShowEventTargetFrameBorder() &&
|
2007-03-30 21:11:41 +00:00
|
|
|
aFrame->PresContext()->PresShell()->GetDrawEventTargetFrame() == aFrame) {
|
2007-02-20 20:22:19 +00:00
|
|
|
aLists.Outlines()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplayGeneric(aFrame, PaintEventTargetBorder, "EventTargetBorder"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
nsresult
|
|
|
|
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsRect& aDirtyRect,
|
|
|
|
nsDisplayList* aList) {
|
2007-07-21 00:34:36 +00:00
|
|
|
if (GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
|
2006-01-26 02:29:17 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// Replaced elements have their visibility handled here, because
|
|
|
|
// they're visually atomic
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (IsFrameOfType(eReplaced) && !IsVisibleForPainting(aBuilder))
|
2006-01-26 02:29:17 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsRect absPosClip;
|
|
|
|
const nsStyleDisplay* disp = GetStyleDisplay();
|
|
|
|
PRBool applyAbsPosClipping =
|
|
|
|
ApplyAbsPosClipping(aBuilder, disp, this, &absPosClip);
|
|
|
|
nsRect dirtyRect = aDirtyRect;
|
2008-09-13 09:42:11 +00:00
|
|
|
|
2009-07-22 00:45:14 +00:00
|
|
|
PRBool inTransform = aBuilder->IsInTransform();
|
2008-09-13 09:42:11 +00:00
|
|
|
/* If we're being transformed, we need to invert the matrix transform so that we don't
|
|
|
|
* grab points in the wrong coordinate system!
|
|
|
|
*/
|
2008-10-01 00:51:05 +00:00
|
|
|
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
2009-07-22 00:45:14 +00:00
|
|
|
disp->HasTransform()) {
|
2008-09-13 09:42:11 +00:00
|
|
|
dirtyRect = nsDisplayTransform::UntransformRect(dirtyRect, this, nsPoint(0, 0));
|
2009-07-22 00:45:14 +00:00
|
|
|
inTransform = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
if (applyAbsPosClipping) {
|
|
|
|
dirtyRect.IntersectRect(dirtyRect,
|
|
|
|
absPosClip - aBuilder->ToReferenceFrame(this));
|
|
|
|
}
|
2008-09-11 00:24:16 +00:00
|
|
|
|
|
|
|
#ifdef MOZ_SVG
|
|
|
|
PRBool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
|
|
|
|
if (usingSVGEffects) {
|
|
|
|
dirtyRect =
|
|
|
|
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
nsDisplayListCollection set;
|
|
|
|
nsresult rv;
|
|
|
|
{
|
|
|
|
nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, PR_TRUE);
|
2009-07-22 00:45:14 +00:00
|
|
|
nsDisplayListBuilder::AutoInTransformSetter
|
|
|
|
inTransformSetter(aBuilder, inTransform);
|
2006-01-26 02:29:17 +00:00
|
|
|
rv = BuildDisplayList(aBuilder, dirtyRect, set);
|
|
|
|
}
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (aBuilder->IsBackgroundOnly()) {
|
|
|
|
set.BlockBorderBackgrounds()->DeleteAll();
|
|
|
|
set.Floats()->DeleteAll();
|
|
|
|
set.Content()->DeleteAll();
|
|
|
|
set.PositionedDescendants()->DeleteAll();
|
|
|
|
set.Outlines()->DeleteAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
// This z-order sort also sorts secondarily by content order. We need to do
|
|
|
|
// this so that boxes produced by the same element are placed together
|
|
|
|
// in the sort. Consider a position:relative inline element that breaks
|
|
|
|
// across lines and has absolutely positioned children; all the abs-pos
|
|
|
|
// children should be z-ordered after all the boxes for the position:relative
|
|
|
|
// element itself.
|
|
|
|
set.PositionedDescendants()->SortByZOrder(aBuilder, GetContent());
|
|
|
|
|
|
|
|
nsRect overflowClip;
|
|
|
|
if (ApplyOverflowClipping(aBuilder, this, disp, &overflowClip)) {
|
|
|
|
nsOverflowClipWrapper wrapper(this, overflowClip, PR_FALSE, PR_FALSE);
|
|
|
|
rv = wrapper.WrapListsInPlace(aBuilder, this, set);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
// We didn't use overflowClip to restrict the dirty rect, since some of the
|
|
|
|
// descendants may not be clipped by it. Even if we end up with unnecessary
|
|
|
|
// display items, they'll be pruned during OptimizeVisibility.
|
|
|
|
|
|
|
|
nsDisplayList resultList;
|
|
|
|
// Now follow the rules of http://www.w3.org/TR/CSS21/zindex.html
|
|
|
|
// 1,2: backgrounds and borders
|
|
|
|
resultList.AppendToTop(set.BorderBackground());
|
|
|
|
// 3: negative z-index children.
|
|
|
|
for (;;) {
|
|
|
|
nsDisplayItem* item = set.PositionedDescendants()->GetBottom();
|
|
|
|
if (item) {
|
|
|
|
nsIFrame* f = item->GetUnderlyingFrame();
|
|
|
|
NS_ASSERTION(f, "After sorting, every item in the list should have an underlying frame");
|
|
|
|
if (nsLayoutUtils::GetZIndex(f) < 0) {
|
|
|
|
set.PositionedDescendants()->RemoveBottom();
|
|
|
|
resultList.AppendToTop(item);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// 4: block backgrounds
|
|
|
|
resultList.AppendToTop(set.BlockBorderBackgrounds());
|
|
|
|
// 5: floats
|
|
|
|
resultList.AppendToTop(set.Floats());
|
2007-07-19 03:50:24 +00:00
|
|
|
// 7: general content
|
2006-01-26 02:29:17 +00:00
|
|
|
resultList.AppendToTop(set.Content());
|
2007-07-19 03:50:24 +00:00
|
|
|
// 7.5: outlines, in content tree order. We need to sort by content order
|
2006-01-26 02:29:17 +00:00
|
|
|
// because an element with outline that breaks and has children with outline
|
|
|
|
// might have placed child outline items between its own outline items.
|
|
|
|
// The element's outline items need to all come before any child outline
|
|
|
|
// items.
|
|
|
|
set.Outlines()->SortByContentOrder(aBuilder, GetContent());
|
2007-02-20 20:22:19 +00:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
DisplayDebugBorders(aBuilder, this, set);
|
|
|
|
#endif
|
2007-03-25 05:30:59 +00:00
|
|
|
resultList.AppendToTop(set.Outlines());
|
2007-07-19 03:50:24 +00:00
|
|
|
// 8, 9: non-negative z-index children
|
|
|
|
resultList.AppendToTop(set.PositionedDescendants());
|
2007-02-20 20:22:19 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
if (applyAbsPosClipping) {
|
2008-04-18 09:21:21 +00:00
|
|
|
nsAbsPosClipWrapper wrapper(this, absPosClip);
|
2006-01-26 02:29:17 +00:00
|
|
|
nsDisplayItem* item = wrapper.WrapList(aBuilder, this, &resultList);
|
|
|
|
if (!item)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
// resultList was emptied
|
|
|
|
resultList.AppendToTop(item);
|
|
|
|
}
|
|
|
|
|
2008-09-11 00:24:16 +00:00
|
|
|
#ifdef MOZ_SVG
|
2008-09-13 09:42:11 +00:00
|
|
|
/* If there are any SVG effects, wrap up the list in an effects list. */
|
2008-09-11 00:24:16 +00:00
|
|
|
if (usingSVGEffects) {
|
2008-09-13 09:42:11 +00:00
|
|
|
nsDisplaySVGEffects* svgList = new (aBuilder) nsDisplaySVGEffects(this, &resultList);
|
|
|
|
if (!svgList)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
/* List now emptied, so add the new list to the top. */
|
|
|
|
resultList.AppendToTop(svgList);
|
2008-09-11 00:24:16 +00:00
|
|
|
} else
|
|
|
|
#endif
|
2008-09-13 09:42:11 +00:00
|
|
|
|
|
|
|
/* If there is any opacity, wrap it up in an opacity list. */
|
2008-09-11 00:24:16 +00:00
|
|
|
if (disp->mOpacity < 1.0f) {
|
2008-09-13 09:42:11 +00:00
|
|
|
nsDisplayOpacity* opacityList = new (aBuilder) nsDisplayOpacity(this, &resultList);
|
|
|
|
if (!opacityList)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
resultList.AppendToTop(opacityList);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we're going to apply a transformation, wrap everything in an
|
|
|
|
* nsDisplayTransform.
|
|
|
|
*/
|
2008-10-01 00:51:05 +00:00
|
|
|
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
|
|
|
disp->HasTransform()) {
|
2008-09-13 09:42:11 +00:00
|
|
|
nsDisplayTransform* transform = new (aBuilder) nsDisplayTransform(this, &resultList);
|
|
|
|
if (!transform)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
resultList.AppendToTop(transform);
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
2008-09-11 00:24:16 +00:00
|
|
|
|
2008-09-13 09:42:11 +00:00
|
|
|
aList->AppendToTop(&resultList);
|
2006-01-26 02:29:17 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsIFrame* aChild,
|
|
|
|
const nsRect& aDirtyRect,
|
|
|
|
const nsDisplayListSet& aLists,
|
|
|
|
PRUint32 aFlags) {
|
|
|
|
// If painting is restricted to just the background of the top level frame,
|
|
|
|
// then we have nothing to do here.
|
|
|
|
if (aBuilder->IsBackgroundOnly())
|
|
|
|
return NS_OK;
|
|
|
|
|
2007-07-21 00:34:36 +00:00
|
|
|
if (aChild->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
|
2006-01-26 02:29:17 +00:00
|
|
|
return NS_OK;
|
2006-01-26 21:03:49 +00:00
|
|
|
|
2006-06-08 03:35:29 +00:00
|
|
|
const nsStyleDisplay* disp = aChild->GetStyleDisplay();
|
2006-01-26 02:29:17 +00:00
|
|
|
// PR_TRUE if this is a real or pseudo stacking context
|
|
|
|
PRBool pseudoStackingContext =
|
|
|
|
(aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
|
2006-06-08 03:35:29 +00:00
|
|
|
// XXX we REALLY need a "are you an inline-block sort of thing?" here!!!
|
2006-01-26 21:03:49 +00:00
|
|
|
if ((aFlags & DISPLAY_CHILD_INLINE) &&
|
2006-09-19 20:58:36 +00:00
|
|
|
(disp->mDisplay != NS_STYLE_DISPLAY_INLINE ||
|
|
|
|
aChild->IsContainingBlock() ||
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
(aChild->IsFrameOfType(eReplaced)))) {
|
2006-09-19 20:58:36 +00:00
|
|
|
// child is a non-inline frame in an inline context, i.e.,
|
2006-01-26 02:29:17 +00:00
|
|
|
// it acts like inline-block or inline-table. Therefore it is a
|
|
|
|
// pseudo-stacking-context.
|
|
|
|
pseudoStackingContext = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dirty rect in child-relative coordinates
|
|
|
|
nsRect dirty = aDirtyRect - aChild->GetOffsetTo(this);
|
|
|
|
|
2006-09-19 20:58:36 +00:00
|
|
|
nsIAtom* childType = aChild->GetType();
|
2006-12-26 17:47:52 +00:00
|
|
|
if (childType == nsGkAtoms::placeholderFrame) {
|
2007-07-08 07:08:04 +00:00
|
|
|
nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(aChild);
|
2006-01-26 02:29:17 +00:00
|
|
|
aChild = placeholder->GetOutOfFlowFrame();
|
|
|
|
NS_ASSERTION(aChild, "No out of flow frame?");
|
2009-09-07 21:43:20 +00:00
|
|
|
if (!aChild || aChild->GetType() == nsGkAtoms::menuPopupFrame)
|
2006-01-26 02:29:17 +00:00
|
|
|
return NS_OK;
|
2006-06-09 21:04:21 +00:00
|
|
|
// update for the new child
|
|
|
|
disp = aChild->GetStyleDisplay();
|
|
|
|
// Make sure that any attempt to use childType below is disappointed. We
|
|
|
|
// could call GetType again but since we don't currently need it, let's
|
|
|
|
// avoid the virtual call.
|
|
|
|
childType = nsnull;
|
2007-07-21 00:34:36 +00:00
|
|
|
// Recheck NS_FRAME_TOO_DEEP_IN_FRAME_TREE
|
|
|
|
if (aChild->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
|
2006-01-26 02:29:17 +00:00
|
|
|
return NS_OK;
|
2007-07-08 07:08:04 +00:00
|
|
|
nsRect* savedDirty = static_cast<nsRect*>
|
|
|
|
(aChild->GetProperty(nsGkAtoms::outOfFlowDirtyRectProperty));
|
2006-01-26 02:29:17 +00:00
|
|
|
if (savedDirty) {
|
|
|
|
dirty = *savedDirty;
|
|
|
|
} else {
|
|
|
|
// The out-of-flow frame did not intersect the dirty area. We may still
|
|
|
|
// need to traverse into it, since it may contain placeholders we need
|
|
|
|
// to enter to reach other out-of-flow frames that are visible.
|
|
|
|
dirty.Empty();
|
|
|
|
}
|
|
|
|
pseudoStackingContext = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2007-03-19 03:25:05 +00:00
|
|
|
if (aBuilder->GetPaintAllFrames()) {
|
|
|
|
dirty = aChild->GetOverflowRect();
|
|
|
|
} else if (!(aChild->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
|
2006-09-19 22:05:33 +00:00
|
|
|
// No need to descend into aChild to catch placeholders for visible
|
|
|
|
// positioned stuff. So see if we can short-circuit frame traversal here.
|
|
|
|
|
2009-03-30 00:29:36 +00:00
|
|
|
// We can stop if aChild's frame subtree's intersection with the
|
|
|
|
// dirty area is empty.
|
2006-09-19 22:05:33 +00:00
|
|
|
// If the child is a scrollframe that we want to ignore, then we need
|
|
|
|
// to descend into it because its scrolled child may intersect the dirty
|
|
|
|
// area even if the scrollframe itself doesn't.
|
2009-03-30 00:29:36 +00:00
|
|
|
if (aChild != aBuilder->GetIgnoreScrollFrame()) {
|
|
|
|
nsRect childDirty;
|
|
|
|
if (!childDirty.IntersectRect(dirty, aChild->GetOverflowRect()))
|
|
|
|
return NS_OK;
|
|
|
|
// Usually we could set dirty to childDirty now but there's no
|
|
|
|
// benefit, and it can be confusing. It can especially confuse
|
|
|
|
// situations where we're going to ignore a scrollframe's clipping;
|
|
|
|
// we wouldn't want to clip the dirty area to the scrollframe's
|
|
|
|
// bounds in that case.
|
|
|
|
}
|
2006-09-19 22:05:33 +00:00
|
|
|
}
|
2006-01-26 02:29:17 +00:00
|
|
|
|
|
|
|
// XXX need to have inline-block and inline-table set pseudoStackingContext
|
|
|
|
|
|
|
|
const nsStyleDisplay* ourDisp = GetStyleDisplay();
|
|
|
|
// REVIEW: Taken from nsBoxFrame::Paint
|
|
|
|
// Don't paint our children if the theme object is a leaf.
|
|
|
|
if (IsThemed(ourDisp) &&
|
2007-03-30 21:11:41 +00:00
|
|
|
!PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
|
2006-01-26 02:29:17 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
2008-09-13 09:42:11 +00:00
|
|
|
// Child is composited if it's transformed, partially transparent, or has
|
|
|
|
// SVG effects.
|
|
|
|
PRBool isComposited = disp->mOpacity != 1.0f ||
|
2008-10-01 00:51:05 +00:00
|
|
|
((aChild->mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
2008-09-13 09:42:11 +00:00
|
|
|
aChild->GetStyleDisplay()->HasTransform())
|
2008-09-11 00:24:16 +00:00
|
|
|
#ifdef MOZ_SVG
|
|
|
|
|| nsSVGIntegrationUtils::UsingEffectsForFrame(aChild)
|
|
|
|
#endif
|
|
|
|
;
|
2006-01-26 02:29:17 +00:00
|
|
|
PRBool isPositioned = disp->IsPositioned();
|
2009-08-31 18:25:35 +00:00
|
|
|
if (isComposited || isPositioned || disp->IsFloating() ||
|
|
|
|
(aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
|
2006-01-26 02:29:17 +00:00
|
|
|
// If you change this, also change IsPseudoStackingContextFromStyle()
|
|
|
|
pseudoStackingContext = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect overflowClip;
|
|
|
|
PRBool applyOverflowClip =
|
|
|
|
ApplyOverflowClipping(aBuilder, aChild, disp, &overflowClip);
|
|
|
|
// Don't use overflowClip to restrict the dirty rect, since some of the
|
|
|
|
// descendants may not be clipped by it. Even if we end up with unnecessary
|
|
|
|
// display items, they'll be pruned during OptimizeVisibility. Note that
|
|
|
|
// this overflow-clipping here only applies to overflow:-moz-hidden-unscrollable;
|
|
|
|
// overflow:hidden etc creates an nsHTML/XULScrollFrame which does its own
|
|
|
|
// clipping.
|
|
|
|
|
|
|
|
nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, pseudoStackingContext);
|
|
|
|
nsresult rv;
|
|
|
|
if (!pseudoStackingContext) {
|
|
|
|
// THIS IS THE COMMON CASE.
|
|
|
|
// Not a pseudo or real stacking context. Do the simple thing and
|
|
|
|
// return early.
|
|
|
|
if (applyOverflowClip) {
|
|
|
|
rv = BuildDisplayListWithOverflowClip(aBuilder, aChild, dirty, aLists,
|
|
|
|
overflowClip);
|
|
|
|
} else {
|
|
|
|
rv = aChild->BuildDisplayList(aBuilder, dirty, aLists);
|
2006-04-17 23:16:46 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = aBuilder->DisplayCaret(aChild, dirty, aLists);
|
|
|
|
}
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
2007-02-20 20:22:19 +00:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
DisplayDebugBorders(aBuilder, aChild, aLists);
|
|
|
|
#endif
|
2006-04-17 23:16:46 +00:00
|
|
|
return rv;
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsDisplayList list;
|
|
|
|
nsDisplayList extraPositionedDescendants;
|
|
|
|
const nsStylePosition* pos = aChild->GetStylePosition();
|
|
|
|
if ((isPositioned && pos->mZIndex.GetUnit() == eStyleUnit_Integer) ||
|
2006-08-03 21:39:39 +00:00
|
|
|
isComposited || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
|
2006-01-26 02:29:17 +00:00
|
|
|
// True stacking context
|
|
|
|
rv = aChild->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
|
2006-04-17 23:16:46 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = aBuilder->DisplayCaret(aChild, dirty, aLists);
|
|
|
|
}
|
2006-01-26 02:29:17 +00:00
|
|
|
} else {
|
|
|
|
nsRect clipRect;
|
|
|
|
PRBool applyAbsPosClipping =
|
|
|
|
ApplyAbsPosClipping(aBuilder, disp, aChild, &clipRect);
|
2007-10-19 17:41:29 +00:00
|
|
|
// A pseudo-stacking context (e.g., a positioned element with z-index auto).
|
2006-01-26 02:29:17 +00:00
|
|
|
// we allow positioned descendants of this element to escape to our
|
|
|
|
// container's positioned descendant list, because they might be
|
|
|
|
// z-index:non-auto
|
|
|
|
nsDisplayListCollection pseudoStack;
|
|
|
|
nsRect clippedDirtyRect = dirty;
|
|
|
|
if (applyAbsPosClipping) {
|
|
|
|
// clipRect is in builder-reference-frame coordinates,
|
|
|
|
// dirty/clippedDirtyRect are in aChild coordinates
|
|
|
|
clippedDirtyRect.IntersectRect(clippedDirtyRect,
|
|
|
|
clipRect - aBuilder->ToReferenceFrame(aChild));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (applyOverflowClip) {
|
|
|
|
rv = BuildDisplayListWithOverflowClip(aBuilder, aChild, clippedDirtyRect,
|
|
|
|
pseudoStack, overflowClip);
|
|
|
|
} else {
|
|
|
|
rv = aChild->BuildDisplayList(aBuilder, clippedDirtyRect, pseudoStack);
|
2006-04-17 23:16:46 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = aBuilder->DisplayCaret(aChild, dirty, aLists);
|
|
|
|
}
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (isPositioned && applyAbsPosClipping) {
|
2008-04-18 09:21:21 +00:00
|
|
|
nsAbsPosClipWrapper wrapper(aChild, clipRect);
|
2006-01-26 02:29:17 +00:00
|
|
|
rv = wrapper.WrapListsInPlace(aBuilder, aChild, pseudoStack);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
list.AppendToTop(pseudoStack.BorderBackground());
|
|
|
|
list.AppendToTop(pseudoStack.BlockBorderBackgrounds());
|
|
|
|
list.AppendToTop(pseudoStack.Floats());
|
|
|
|
list.AppendToTop(pseudoStack.Content());
|
2007-07-19 03:50:24 +00:00
|
|
|
list.AppendToTop(pseudoStack.Outlines());
|
2006-01-26 02:29:17 +00:00
|
|
|
extraPositionedDescendants.AppendToTop(pseudoStack.PositionedDescendants());
|
2007-02-20 20:22:19 +00:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
DisplayDebugBorders(aBuilder, aChild, aLists);
|
|
|
|
#endif
|
2006-01-26 02:29:17 +00:00
|
|
|
}
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2006-08-03 21:39:39 +00:00
|
|
|
if (isPositioned || isComposited ||
|
|
|
|
(aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
|
2006-01-26 02:29:17 +00:00
|
|
|
// Genuine stacking contexts, and positioned pseudo-stacking-contexts,
|
|
|
|
// go in this level.
|
|
|
|
rv = aLists.PositionedDescendants()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplayWrapList(aChild, &list));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
} else if (disp->IsFloating()) {
|
|
|
|
rv = aLists.Floats()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplayWrapList(aChild, &list));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
} else {
|
|
|
|
aLists.Content()->AppendToTop(&list);
|
|
|
|
}
|
|
|
|
// We delay placing the positioned descendants of positioned frames to here,
|
|
|
|
// because in the absence of z-index this is the correct order for them.
|
|
|
|
// This doesn't affect correctness because the positioned descendants list
|
|
|
|
// is sorted by z-order and content in BuildDisplayListForStackingContext,
|
|
|
|
// but it means that sort routine needs to do less work.
|
|
|
|
aLists.PositionedDescendants()->AppendToTop(&extraPositionedDescendants);
|
|
|
|
return NS_OK;
|
2002-12-23 22:05:47 +00:00
|
|
|
}
|
|
|
|
|
2005-04-07 03:59:02 +00:00
|
|
|
nsresult
|
|
|
|
nsIFrame::CreateWidgetForView(nsIView* aView)
|
|
|
|
{
|
|
|
|
return aView->CreateWidget(kWidgetCID);
|
|
|
|
}
|
|
|
|
|
2000-02-11 01:24:59 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::GetContentForEvent(nsPresContext* aPresContext,
|
2000-02-11 01:24:59 +00:00
|
|
|
nsEvent* aEvent,
|
|
|
|
nsIContent** aContent)
|
|
|
|
{
|
2009-09-02 02:46:33 +00:00
|
|
|
nsIFrame* f = nsLayoutUtils::GetNonGeneratedAncestor(this);
|
|
|
|
*aContent = f->GetContent();
|
2003-06-27 18:13:48 +00:00
|
|
|
NS_IF_ADDREF(*aContent);
|
|
|
|
return NS_OK;
|
2000-02-11 01:24:59 +00:00
|
|
|
}
|
|
|
|
|
2006-05-03 17:02:37 +00:00
|
|
|
void
|
|
|
|
nsFrame::FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent)
|
|
|
|
{
|
2009-03-06 18:12:20 +00:00
|
|
|
nsIContent* target = aContent ? aContent : mContent;
|
|
|
|
|
|
|
|
if (target) {
|
|
|
|
nsRefPtr<nsPLDOMEvent> event =
|
|
|
|
new nsPLDOMEvent(target, aDOMEventName, PR_FALSE);
|
2006-05-10 17:30:15 +00:00
|
|
|
if (!event || NS_FAILED(event->PostDOMEvent()))
|
|
|
|
NS_WARNING("Failed to dispatch nsPLDOMEvent");
|
2006-05-03 17:02:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-18 15:54:23 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::HandleEvent(nsPresContext* aPresContext,
|
1998-12-18 15:54:23 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2006-11-16 21:35:39 +00:00
|
|
|
|
|
|
|
if (aEvent->message == NS_MOUSE_MOVE) {
|
|
|
|
return HandleDrag(aPresContext, aEvent, aEventStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aEvent->eventStructType == NS_MOUSE_EVENT &&
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) {
|
2006-11-16 21:35:39 +00:00
|
|
|
if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
|
2003-12-21 05:36:36 +00:00
|
|
|
HandlePress(aPresContext, aEvent, aEventStatus);
|
2006-11-16 21:35:39 +00:00
|
|
|
} else if (aEvent->message == NS_MOUSE_BUTTON_UP) {
|
2003-12-21 05:36:36 +00:00
|
|
|
HandleRelease(aPresContext, aEvent, aEventStatus);
|
2006-11-16 21:35:39 +00:00
|
|
|
}
|
|
|
|
}
|
1998-04-27 16:44:52 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-03-16 23:45:39 +00:00
|
|
|
NS_IMETHODIMP
|
2007-11-22 20:47:33 +00:00
|
|
|
nsFrame::GetDataForTableSelection(const nsFrameSelection *aFrameSelection,
|
2002-03-22 15:25:08 +00:00
|
|
|
nsIPresShell *aPresShell, nsMouseEvent *aMouseEvent,
|
2000-12-20 22:13:54 +00:00
|
|
|
nsIContent **aParentContent, PRInt32 *aContentOffset, PRInt32 *aTarget)
|
2000-03-16 23:45:39 +00:00
|
|
|
{
|
2002-03-22 15:25:08 +00:00
|
|
|
if (!aFrameSelection || !aPresShell || !aMouseEvent || !aParentContent || !aContentOffset || !aTarget)
|
2000-03-16 23:45:39 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
*aParentContent = nsnull;
|
|
|
|
*aContentOffset = 0;
|
|
|
|
*aTarget = 0;
|
|
|
|
|
2002-03-22 15:25:08 +00:00
|
|
|
PRInt16 displaySelection;
|
|
|
|
nsresult result = aPresShell->GetSelectionFlags(&displaySelection);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
2006-04-26 02:01:07 +00:00
|
|
|
PRBool selectingTableCells = aFrameSelection->GetTableCellSelection();
|
2002-03-22 15:25:08 +00:00
|
|
|
|
|
|
|
// DISPLAY_ALL means we're in an editor.
|
|
|
|
// If already in cell selection mode,
|
|
|
|
// continue selecting with mouse drag or end on mouse up,
|
|
|
|
// or when using shift key to extend block of cells
|
|
|
|
// (Mouse down does normal selection unless Ctrl/Cmd is pressed)
|
|
|
|
PRBool doTableSelection =
|
|
|
|
displaySelection == nsISelectionDisplay::DISPLAY_ALL && selectingTableCells &&
|
|
|
|
(aMouseEvent->message == NS_MOUSE_MOVE ||
|
2006-11-16 21:35:39 +00:00
|
|
|
(aMouseEvent->message == NS_MOUSE_BUTTON_UP &&
|
|
|
|
aMouseEvent->button == nsMouseEvent::eLeftButton) ||
|
2002-03-22 15:25:08 +00:00
|
|
|
aMouseEvent->isShift);
|
|
|
|
|
|
|
|
if (!doTableSelection)
|
|
|
|
{
|
|
|
|
// In Browser, special 'table selection' key must be pressed for table selection
|
|
|
|
// or when just Shift is pressed and we're already in table/cell selection mode
|
2007-10-01 23:20:37 +00:00
|
|
|
#ifdef XP_MACOSX
|
2002-03-22 15:25:08 +00:00
|
|
|
doTableSelection = aMouseEvent->isMeta || (aMouseEvent->isShift && selectingTableCells);
|
2000-03-16 23:45:39 +00:00
|
|
|
#else
|
2002-03-22 15:25:08 +00:00
|
|
|
doTableSelection = aMouseEvent->isControl || (aMouseEvent->isShift && selectingTableCells);
|
2000-03-16 23:45:39 +00:00
|
|
|
#endif
|
2000-05-31 00:07:58 +00:00
|
|
|
}
|
2002-03-22 15:25:08 +00:00
|
|
|
if (!doTableSelection)
|
|
|
|
return NS_OK;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
|
|
|
// Get the cell frame or table frame (or parent) of the current content node
|
|
|
|
nsIFrame *frame = this;
|
|
|
|
PRBool foundCell = PR_FALSE;
|
|
|
|
PRBool foundTable = PR_FALSE;
|
2000-08-02 01:47:55 +00:00
|
|
|
|
|
|
|
// Get the limiting node to stop parent frame search
|
2006-04-26 02:01:07 +00:00
|
|
|
nsIContent* limiter = aFrameSelection->GetLimiter();
|
2000-08-02 01:47:55 +00:00
|
|
|
|
2000-05-31 00:07:58 +00:00
|
|
|
//We don't initiate row/col selection from here now,
|
|
|
|
// but we may in future
|
|
|
|
//PRBool selectColumn = PR_FALSE;
|
|
|
|
//PRBool selectRow = PR_FALSE;
|
2006-04-26 02:01:07 +00:00
|
|
|
|
|
|
|
result = NS_OK;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
|
|
|
while (frame && NS_SUCCEEDED(result))
|
|
|
|
{
|
|
|
|
// Check for a table cell by querying to a known CellFrame interface
|
2009-01-12 19:20:59 +00:00
|
|
|
nsITableCellLayout *cellElement = do_QueryFrame(frame);
|
|
|
|
if (cellElement)
|
2000-03-16 23:45:39 +00:00
|
|
|
{
|
|
|
|
foundCell = PR_TRUE;
|
2000-05-31 00:07:58 +00:00
|
|
|
//TODO: If we want to use proximity to top or left border
|
|
|
|
// for row and column selection, this is the place to do it
|
2000-03-16 23:45:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If not a cell, check for table
|
|
|
|
// This will happen when starting frame is the table or child of a table,
|
|
|
|
// such as a row (we were inbetween cells or in table border)
|
2009-01-12 19:20:59 +00:00
|
|
|
nsITableLayout *tableElement = do_QueryFrame(frame);
|
|
|
|
if (tableElement)
|
2000-03-16 23:45:39 +00:00
|
|
|
{
|
|
|
|
foundTable = PR_TRUE;
|
2000-05-16 03:03:13 +00:00
|
|
|
//TODO: How can we select row when along left table edge
|
|
|
|
// or select column when along top edge?
|
2000-03-16 23:45:39 +00:00
|
|
|
break;
|
2000-03-21 06:04:02 +00:00
|
|
|
} else {
|
2003-06-27 18:13:48 +00:00
|
|
|
frame = frame->GetParent();
|
|
|
|
result = NS_OK;
|
2000-08-02 01:47:55 +00:00
|
|
|
// Stop if we have hit the selection's limiting content node
|
2006-04-26 02:01:07 +00:00
|
|
|
if (frame && frame->GetContent() == limiter)
|
2003-06-27 18:13:48 +00:00
|
|
|
break;
|
2000-03-16 23:45:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We aren't in a cell or table
|
|
|
|
if (!foundCell && !foundTable) return NS_OK;
|
|
|
|
|
2003-06-27 18:13:48 +00:00
|
|
|
nsIContent* tableOrCellContent = frame->GetContent();
|
2000-03-16 23:45:39 +00:00
|
|
|
if (!tableOrCellContent) return NS_ERROR_FAILURE;
|
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
nsCOMPtr<nsIContent> parentContent = tableOrCellContent->GetParent();
|
2000-03-16 23:45:39 +00:00
|
|
|
if (!parentContent) return NS_ERROR_FAILURE;
|
|
|
|
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 offset = parentContent->IndexOf(tableOrCellContent);
|
2000-03-16 23:45:39 +00:00
|
|
|
// Not likely?
|
|
|
|
if (offset < 0) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Everything is OK -- set the return values
|
|
|
|
*aParentContent = parentContent;
|
|
|
|
NS_ADDREF(*aParentContent);
|
|
|
|
|
|
|
|
*aContentOffset = offset;
|
|
|
|
|
2000-05-31 00:07:58 +00:00
|
|
|
#if 0
|
2000-05-16 03:03:13 +00:00
|
|
|
if (selectRow)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_ROW;
|
2000-05-16 03:03:13 +00:00
|
|
|
else if (selectColumn)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_COLUMN;
|
2000-05-31 00:07:58 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (foundCell)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_CELL;
|
2000-05-16 03:03:13 +00:00
|
|
|
else if (foundTable)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_TABLE;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::IsSelectable(PRBool* aSelectable, PRUint8* aSelectStyle) const
|
|
|
|
{
|
2005-11-20 22:05:24 +00:00
|
|
|
if (!aSelectable) //it's ok if aSelectStyle is null
|
2000-08-12 01:00:14 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
2000-08-05 04:41:33 +00:00
|
|
|
|
|
|
|
// Like 'visibility', we must check all the parents: if a parent
|
|
|
|
// is not selectable, none of its children is selectable.
|
2000-08-12 01:00:14 +00:00
|
|
|
//
|
|
|
|
// The -moz-all value acts similarly: if a frame has 'user-select:-moz-all',
|
|
|
|
// all its children are selectable, even those with 'user-select:none'.
|
|
|
|
//
|
|
|
|
// As a result, if 'none' and '-moz-all' are not present in the frame hierarchy,
|
|
|
|
// aSelectStyle returns the first style that is not AUTO. If these values
|
|
|
|
// are present in the frame hierarchy, aSelectStyle returns the style of the
|
|
|
|
// topmost parent that has either 'none' or '-moz-all'.
|
|
|
|
//
|
|
|
|
// For instance, if the frame hierarchy is:
|
|
|
|
// AUTO -> _MOZ_ALL -> NONE -> TEXT, the returned value is _MOZ_ALL
|
|
|
|
// TEXT -> NONE -> AUTO -> _MOZ_ALL, the returned value is NONE
|
|
|
|
// _MOZ_ALL -> TEXT -> AUTO -> AUTO, the returned value is _MOZ_ALL
|
|
|
|
// AUTO -> CELL -> TEXT -> AUTO, the returned value is TEXT
|
|
|
|
//
|
|
|
|
PRUint8 selectStyle = NS_STYLE_USER_SELECT_AUTO;
|
|
|
|
nsIFrame* frame = (nsIFrame*)this;
|
|
|
|
|
2003-06-27 18:13:48 +00:00
|
|
|
while (frame) {
|
2003-05-15 03:42:21 +00:00
|
|
|
const nsStyleUIReset* userinterface = frame->GetStyleUIReset();
|
|
|
|
switch (userinterface->mUserSelect) {
|
|
|
|
case NS_STYLE_USER_SELECT_ALL:
|
|
|
|
case NS_STYLE_USER_SELECT_NONE:
|
|
|
|
case NS_STYLE_USER_SELECT_MOZ_ALL:
|
|
|
|
// override the previous values
|
|
|
|
selectStyle = userinterface->mUserSelect;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// otherwise return the first value which is not 'auto'
|
|
|
|
if (selectStyle == NS_STYLE_USER_SELECT_AUTO) {
|
2000-08-08 23:48:42 +00:00
|
|
|
selectStyle = userinterface->mUserSelect;
|
2003-05-15 03:42:21 +00:00
|
|
|
}
|
|
|
|
break;
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
2003-06-27 18:13:48 +00:00
|
|
|
frame = frame->GetParent();
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
2000-08-08 23:48:42 +00:00
|
|
|
|
2000-08-12 01:00:14 +00:00
|
|
|
// convert internal values to standard values
|
|
|
|
if (selectStyle == NS_STYLE_USER_SELECT_AUTO)
|
|
|
|
selectStyle = NS_STYLE_USER_SELECT_TEXT;
|
|
|
|
else
|
|
|
|
if (selectStyle == NS_STYLE_USER_SELECT_MOZ_ALL)
|
|
|
|
selectStyle = NS_STYLE_USER_SELECT_ALL;
|
2005-09-11 19:22:57 +00:00
|
|
|
else
|
|
|
|
if (selectStyle == NS_STYLE_USER_SELECT_MOZ_NONE)
|
|
|
|
selectStyle = NS_STYLE_USER_SELECT_NONE;
|
2000-08-12 01:00:14 +00:00
|
|
|
|
|
|
|
// return stuff
|
|
|
|
if (aSelectable)
|
|
|
|
*aSelectable = (selectStyle != NS_STYLE_USER_SELECT_NONE);
|
|
|
|
if (aSelectStyle)
|
|
|
|
*aSelectStyle = selectStyle;
|
2001-06-20 04:40:17 +00:00
|
|
|
if (mState & NS_FRAME_GENERATED_CONTENT)
|
2001-06-20 06:40:48 +00:00
|
|
|
*aSelectable = PR_FALSE;
|
2000-08-05 04:41:33 +00:00
|
|
|
return NS_OK;
|
2000-04-12 03:04:11 +00:00
|
|
|
}
|
|
|
|
|
1998-05-08 18:33:42 +00:00
|
|
|
/**
|
|
|
|
* Handles the Mouse Press Event for the frame
|
|
|
|
*/
|
1999-02-12 17:45:58 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::HandlePress(nsPresContext* aPresContext,
|
1999-02-12 17:45:58 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-27 16:44:52 +00:00
|
|
|
{
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aEventStatus);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-09-14 08:47:46 +00:00
|
|
|
|
2002-02-20 07:23:35 +00:00
|
|
|
//We often get out of sync state issues with mousedown events that
|
|
|
|
//get interrupted by alerts/dialogs.
|
|
|
|
//Check with the ESM to see if we should process this one
|
|
|
|
PRBool eventOK;
|
2004-02-27 17:17:37 +00:00
|
|
|
aPresContext->EventStateManager()->EventStatusOK(aEvent, &eventOK);
|
2002-02-20 07:23:35 +00:00
|
|
|
if (!eventOK)
|
|
|
|
return NS_OK;
|
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
nsresult rv;
|
2003-12-21 05:36:36 +00:00
|
|
|
nsIPresShell *shell = aPresContext->GetPresShell();
|
2000-09-14 08:47:46 +00:00
|
|
|
if (!shell)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2004-07-30 06:04:57 +00:00
|
|
|
// if we are in Navigator and the click is in a draggable node, we don't want
|
|
|
|
// to start selection because we don't want to interfere with a potential
|
|
|
|
// drag of said node and steal all its glory.
|
2001-12-18 01:29:49 +00:00
|
|
|
PRInt16 isEditor = 0;
|
|
|
|
shell->GetSelectionFlags ( &isEditor );
|
|
|
|
//weaaak. only the editor can display frame selction not just text and images
|
|
|
|
isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
|
|
|
|
|
2005-08-23 03:57:07 +00:00
|
|
|
nsInputEvent* keyEvent = (nsInputEvent*)aEvent;
|
2008-04-18 13:27:02 +00:00
|
|
|
if (!keyEvent->isAlt) {
|
2002-04-01 04:27:50 +00:00
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
for (nsIContent* content = mContent; content;
|
|
|
|
content = content->GetParent()) {
|
2008-04-18 13:27:02 +00:00
|
|
|
if (nsContentUtils::ContentIsDraggable(content) &&
|
|
|
|
!content->IsEditable()) {
|
2004-07-30 06:04:57 +00:00
|
|
|
// coordinate stuff is the fix for bug #55921
|
2005-08-23 03:57:07 +00:00
|
|
|
if ((mRect - GetPosition()).Contains(
|
|
|
|
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this)))
|
2004-07-30 06:04:57 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2008-04-18 13:27:02 +00:00
|
|
|
}
|
2000-09-14 08:47:46 +00:00
|
|
|
|
|
|
|
// check whether style allows selection
|
2000-11-09 00:06:54 +00:00
|
|
|
// if not, don't tell selection the mouse event even occurred.
|
2000-08-08 23:48:42 +00:00
|
|
|
PRBool selectable;
|
|
|
|
PRUint8 selectStyle;
|
|
|
|
rv = IsSelectable(&selectable, &selectStyle);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
2000-09-14 08:47:46 +00:00
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
// check for select: none
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable)
|
2000-05-26 06:42:29 +00:00
|
|
|
return NS_OK;
|
2000-05-16 13:52:28 +00:00
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
// When implementing NS_STYLE_USER_SELECT_ELEMENT, NS_STYLE_USER_SELECT_ELEMENTS and
|
|
|
|
// NS_STYLE_USER_SELECT_TOGGLE, need to change this logic
|
|
|
|
PRBool useFrameSelection = (selectStyle == NS_STYLE_USER_SELECT_TEXT);
|
|
|
|
|
2009-09-13 13:13:16 +00:00
|
|
|
// If the mouse is dragged outside the nearest enclosing scrollable area
|
|
|
|
// while making a selection, the area will be scrolled. To do this, capture
|
|
|
|
// the mouse on the nearest scrollable frame. If there isn't a scrollable
|
|
|
|
// frame, or something else is already capturing the mouse, there's no
|
|
|
|
// reason to capture.
|
|
|
|
if (!nsIPresShell::GetCapturingContent()) {
|
|
|
|
nsIFrame* checkFrame = this;
|
|
|
|
nsIScrollableFrame *scrollFrame = nsnull;
|
|
|
|
while (checkFrame) {
|
|
|
|
scrollFrame = do_QueryFrame(checkFrame);
|
|
|
|
if (scrollFrame) {
|
|
|
|
nsIPresShell::SetCapturingContent(checkFrame->GetContent(), CAPTURE_IGNOREALLOWED);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
checkFrame = checkFrame->GetParent();
|
|
|
|
}
|
|
|
|
}
|
2009-03-30 10:12:35 +00:00
|
|
|
|
2006-02-21 00:49:04 +00:00
|
|
|
// XXX This is screwy; it really should use the selection frame, not the
|
|
|
|
// event frame
|
2007-11-22 20:47:33 +00:00
|
|
|
const nsFrameSelection* frameselection = nsnull;
|
2000-08-08 23:48:42 +00:00
|
|
|
if (useFrameSelection)
|
2007-11-22 20:47:33 +00:00
|
|
|
frameselection = GetConstFrameSelection();
|
2006-02-21 00:49:04 +00:00
|
|
|
else
|
2007-11-22 20:47:33 +00:00
|
|
|
frameselection = shell->ConstFrameSelection();
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2006-04-26 02:01:07 +00:00
|
|
|
if (frameselection->GetDisplaySelection() == nsISelectionController::SELECTION_OFF)
|
2006-02-21 00:49:04 +00:00
|
|
|
return NS_OK;//nothing to do we cannot affect selection from here
|
2000-05-11 04:25:43 +00:00
|
|
|
|
1999-09-11 00:18:02 +00:00
|
|
|
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2007-10-01 23:20:37 +00:00
|
|
|
#ifdef XP_MACOSX
|
2000-08-09 22:33:03 +00:00
|
|
|
if (me->isControl)
|
|
|
|
return NS_OK;//short ciruit. hard coded for mac due to time restraints.
|
2008-10-17 19:46:33 +00:00
|
|
|
PRBool control = me->isMeta;
|
|
|
|
#else
|
|
|
|
PRBool control = me->isControl;
|
2000-08-09 22:33:03 +00:00
|
|
|
#endif
|
2008-10-17 19:46:33 +00:00
|
|
|
|
2007-11-22 20:47:33 +00:00
|
|
|
nsCOMPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
|
1999-09-25 23:33:02 +00:00
|
|
|
if (me->clickCount >1 )
|
2000-05-16 22:16:05 +00:00
|
|
|
{
|
2007-11-22 20:47:33 +00:00
|
|
|
// These methods aren't const but can't actually delete anything,
|
|
|
|
// so no need for nsWeakFrame.
|
|
|
|
fc->SetMouseDownState(PR_TRUE);
|
|
|
|
fc->SetMouseDoubleDown(PR_TRUE);
|
2008-10-17 19:46:33 +00:00
|
|
|
return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
1998-07-27 18:05:35 +00:00
|
|
|
|
2009-03-30 10:12:35 +00:00
|
|
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
|
|
|
ContentOffsets offsets = GetContentOffsetsFromPoint(pt);
|
|
|
|
|
2006-02-27 05:57:37 +00:00
|
|
|
if (!offsets.content)
|
|
|
|
return NS_ERROR_FAILURE;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2000-05-31 00:07:58 +00:00
|
|
|
// Let Ctrl/Cmd+mouse down do table selection instead of drag initiation
|
|
|
|
nsCOMPtr<nsIContent>parentContent;
|
|
|
|
PRInt32 contentOffset;
|
2000-12-20 22:13:54 +00:00
|
|
|
PRInt32 target;
|
2002-03-22 15:25:08 +00:00
|
|
|
rv = GetDataForTableSelection(frameselection, shell, me, getter_AddRefs(parentContent), &contentOffset, &target);
|
2000-05-31 00:07:58 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && parentContent)
|
|
|
|
{
|
2007-11-22 20:47:33 +00:00
|
|
|
fc->SetMouseDownState(PR_TRUE);
|
|
|
|
return fc->HandleTableSelection(parentContent, contentOffset, target, me);
|
2000-05-31 00:07:58 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 20:47:33 +00:00
|
|
|
fc->SetDelayedCaretData(0);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2006-12-16 14:40:44 +00:00
|
|
|
// Check if any part of this frame is selected, and if the
|
|
|
|
// user clicked inside the selected region. If so, we delay
|
|
|
|
// starting a new selection since the user may be trying to
|
|
|
|
// drag the selected region to some other app.
|
|
|
|
|
|
|
|
SelectionDetails *details = 0;
|
|
|
|
PRBool isSelected = ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
|
|
|
|
|
|
|
|
if (isSelected)
|
2000-05-16 22:16:05 +00:00
|
|
|
{
|
2008-10-20 20:53:40 +00:00
|
|
|
PRBool inSelection = PR_FALSE;
|
2006-12-16 14:40:44 +00:00
|
|
|
details = frameselection->LookUpSelection(offsets.content, 0,
|
|
|
|
offsets.EndOffset(), PR_FALSE);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2006-12-16 14:40:44 +00:00
|
|
|
//
|
|
|
|
// If there are any details, check to see if the user clicked
|
|
|
|
// within any selected region of the frame.
|
|
|
|
//
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2008-10-20 20:53:40 +00:00
|
|
|
SelectionDetails *curDetail = details;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2008-10-20 20:53:40 +00:00
|
|
|
while (curDetail)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// If the user clicked inside a selection, then just
|
|
|
|
// return without doing anything. We will handle placing
|
|
|
|
// the caret later on when the mouse is released. We ignore
|
|
|
|
// the spellcheck and find selections.
|
|
|
|
//
|
|
|
|
if (curDetail->mType != nsISelectionController::SELECTION_SPELLCHECK &&
|
|
|
|
curDetail->mType != nsISelectionController::SELECTION_FIND &&
|
|
|
|
curDetail->mStart <= offsets.StartOffset() &&
|
|
|
|
offsets.EndOffset() <= curDetail->mEnd)
|
2000-03-16 23:45:39 +00:00
|
|
|
{
|
2008-10-20 20:53:40 +00:00
|
|
|
inSelection = PR_TRUE;
|
1998-12-14 18:34:14 +00:00
|
|
|
}
|
2006-12-16 14:40:44 +00:00
|
|
|
|
2008-10-20 20:53:40 +00:00
|
|
|
SelectionDetails *nextDetail = curDetail->mNext;
|
|
|
|
delete curDetail;
|
|
|
|
curDetail = nextDetail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inSelection) {
|
|
|
|
fc->SetMouseDownState(PR_FALSE);
|
|
|
|
fc->SetDelayedCaretData(me);
|
|
|
|
return NS_OK;
|
1998-12-14 18:34:14 +00:00
|
|
|
}
|
|
|
|
}
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2007-11-22 20:47:33 +00:00
|
|
|
fc->SetMouseDownState(PR_TRUE);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2007-11-22 20:47:33 +00:00
|
|
|
// Do not touch any nsFrame members after this point without adding
|
|
|
|
// weakFrame checks.
|
|
|
|
rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
|
|
|
|
offsets.EndOffset(), me->isShift, control,
|
|
|
|
offsets.associateWithNext);
|
2006-02-27 05:57:37 +00:00
|
|
|
|
2003-04-07 14:28:51 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2006-02-27 05:57:37 +00:00
|
|
|
if (offsets.offset != offsets.secondaryOffset)
|
2007-11-22 20:47:33 +00:00
|
|
|
fc->MaintainSelection();
|
2003-07-21 19:51:34 +00:00
|
|
|
|
2006-02-27 05:57:37 +00:00
|
|
|
if (isEditor && !me->isShift &&
|
|
|
|
(offsets.EndOffset() - offsets.StartOffset()) == 1)
|
2003-04-07 14:28:51 +00:00
|
|
|
{
|
|
|
|
// A single node is selected and we aren't extending an existing
|
2005-12-07 23:08:39 +00:00
|
|
|
// selection, which means the user clicked directly on an object (either
|
|
|
|
// -moz-user-select: all or a non-text node without children).
|
|
|
|
// Therefore, disable selection extension during mouse moves.
|
|
|
|
// XXX This is a bit hacky; shouldn't editor be able to deal with this?
|
2007-11-22 20:47:33 +00:00
|
|
|
fc->SetMouseDownState(PR_FALSE);
|
2003-04-07 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
2005-12-07 23:08:39 +00:00
|
|
|
|
1999-05-17 00:21:18 +00:00
|
|
|
/**
|
2000-05-16 22:48:28 +00:00
|
|
|
* Multiple Mouse Press -- line or paragraph selection -- for the frame.
|
|
|
|
* Wouldn't it be nice if this didn't have to be hardwired into Frame code?
|
1999-05-17 00:21:18 +00:00
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
2008-10-17 19:46:33 +00:00
|
|
|
nsGUIEvent* aEvent,
|
|
|
|
nsEventStatus* aEventStatus,
|
|
|
|
PRBool aControlHeld)
|
1999-05-17 00:21:18 +00:00
|
|
|
{
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aEventStatus);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-04-30 18:56:26 +00:00
|
|
|
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
|
1999-09-11 00:18:02 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
|
|
|
|
// Find out whether we're doing line or paragraph selection.
|
2005-08-18 17:09:16 +00:00
|
|
|
// If browser.triple_click_selects_paragraph is true, triple-click selects paragraph.
|
|
|
|
// Otherwise, triple-click selects line, and quadruple-click selects paragraph
|
|
|
|
// (on platforms that support quadruple-click).
|
2005-12-07 23:08:39 +00:00
|
|
|
nsSelectionAmount beginAmount, endAmount;
|
1999-09-11 00:18:02 +00:00
|
|
|
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
2000-05-16 22:48:28 +00:00
|
|
|
if (!me) return NS_OK;
|
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
if (me->clickCount == 4) {
|
|
|
|
beginAmount = endAmount = eSelectParagraph;
|
|
|
|
} else if (me->clickCount == 3) {
|
|
|
|
if (nsContentUtils::GetBoolPref("browser.triple_click_selects_paragraph")) {
|
|
|
|
beginAmount = endAmount = eSelectParagraph;
|
|
|
|
} else {
|
|
|
|
beginAmount = eSelectBeginLine;
|
|
|
|
endAmount = eSelectEndLine;
|
|
|
|
}
|
|
|
|
} else if (me->clickCount == 2) {
|
|
|
|
// We only want inline frames; PeekBackwardAndForward dislikes blocks
|
|
|
|
beginAmount = endAmount = eSelectWord;
|
|
|
|
} else {
|
1999-09-11 00:18:02 +00:00
|
|
|
return NS_OK;
|
2005-12-07 23:08:39 +00:00
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
|
2005-09-04 20:04:23 +00:00
|
|
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
2006-02-27 05:57:37 +00:00
|
|
|
ContentOffsets offsets = GetContentOffsetsFromPoint(pt);
|
|
|
|
if (!offsets.content) return NS_ERROR_FAILURE;
|
2005-12-07 23:08:39 +00:00
|
|
|
|
2006-04-26 02:01:07 +00:00
|
|
|
nsIFrame* theFrame;
|
2005-12-07 23:08:39 +00:00
|
|
|
PRInt32 offset;
|
|
|
|
// Maybe make this a static helper?
|
2007-11-22 20:47:33 +00:00
|
|
|
const nsFrameSelection* frameSelection =
|
|
|
|
PresContext()->GetPresShell()->ConstFrameSelection();
|
|
|
|
theFrame = frameSelection->
|
2006-02-27 05:57:37 +00:00
|
|
|
GetFrameForNodeOffset(offsets.content, offsets.offset,
|
2006-04-26 02:01:07 +00:00
|
|
|
nsFrameSelection::HINT(offsets.associateWithNext),
|
|
|
|
&offset);
|
|
|
|
if (!theFrame)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
nsFrame* frame = static_cast<nsFrame*>(theFrame);
|
2005-12-07 23:08:39 +00:00
|
|
|
|
|
|
|
return frame->PeekBackwardAndForward(beginAmount, endAmount,
|
2006-02-27 05:57:37 +00:00
|
|
|
offsets.offset, aPresContext,
|
2008-10-17 19:46:33 +00:00
|
|
|
beginAmount != eSelectWord,
|
|
|
|
aControlHeld);
|
2000-05-16 22:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
|
|
|
|
nsSelectionAmount aAmountForward,
|
|
|
|
PRInt32 aStartPos,
|
2004-07-31 23:15:21 +00:00
|
|
|
nsPresContext* aPresContext,
|
2008-10-17 19:46:33 +00:00
|
|
|
PRBool aJumpLines,
|
|
|
|
PRBool aMultipleSelection)
|
2000-05-16 22:48:28 +00:00
|
|
|
{
|
2007-01-04 16:47:04 +00:00
|
|
|
nsIFrame* baseFrame = this;
|
|
|
|
PRInt32 baseOffset = aStartPos;
|
2008-10-17 19:46:33 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
2007-01-04 16:47:04 +00:00
|
|
|
if (aAmountBack == eSelectWord) {
|
|
|
|
// To avoid selecting the previous word when at start of word,
|
|
|
|
// first move one character forward.
|
|
|
|
nsPeekOffsetStruct pos;
|
|
|
|
pos.SetData(eSelectCharacter,
|
|
|
|
eDirNext,
|
|
|
|
aStartPos,
|
|
|
|
0,
|
|
|
|
aJumpLines,
|
|
|
|
PR_TRUE, //limit on scrolled views
|
|
|
|
PR_FALSE,
|
|
|
|
PR_FALSE);
|
|
|
|
rv = PeekOffset(&pos);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
baseFrame = pos.mResultFrame;
|
|
|
|
baseOffset = pos.mContentOffset;
|
|
|
|
}
|
|
|
|
}
|
2008-10-17 19:46:33 +00:00
|
|
|
|
|
|
|
// Use peek offset one way then the other:
|
2000-05-16 22:48:28 +00:00
|
|
|
nsPeekOffsetStruct startpos;
|
2006-07-13 06:06:29 +00:00
|
|
|
startpos.SetData(aAmountBack,
|
2000-05-16 22:48:28 +00:00
|
|
|
eDirPrevious,
|
2007-01-04 16:47:04 +00:00
|
|
|
baseOffset,
|
2006-07-13 06:06:29 +00:00
|
|
|
0,
|
2002-04-16 02:42:09 +00:00
|
|
|
aJumpLines,
|
2003-01-09 20:56:53 +00:00
|
|
|
PR_TRUE, //limit on scrolled views
|
2006-04-08 14:45:48 +00:00
|
|
|
PR_FALSE,
|
2003-01-09 20:56:53 +00:00
|
|
|
PR_FALSE);
|
2007-01-04 16:47:04 +00:00
|
|
|
rv = baseFrame->PeekOffset(&startpos);
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-01-04 16:47:04 +00:00
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
nsPeekOffsetStruct endpos;
|
2006-07-13 06:06:29 +00:00
|
|
|
endpos.SetData(aAmountForward,
|
2000-05-16 22:48:28 +00:00
|
|
|
eDirNext,
|
2006-07-13 06:06:29 +00:00
|
|
|
aStartPos,
|
|
|
|
0,
|
2002-04-16 02:42:09 +00:00
|
|
|
aJumpLines,
|
2003-01-09 20:56:53 +00:00
|
|
|
PR_TRUE, //limit on scrolled views
|
2006-04-08 14:45:48 +00:00
|
|
|
PR_FALSE,
|
2003-01-09 20:56:53 +00:00
|
|
|
PR_FALSE);
|
2006-09-11 20:43:01 +00:00
|
|
|
rv = PeekOffset(&endpos);
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2008-10-17 19:46:33 +00:00
|
|
|
// Keep frameSelection alive.
|
|
|
|
nsRefPtr<nsFrameSelection> frameSelection = GetFrameSelection();
|
|
|
|
|
|
|
|
rv = frameSelection->HandleClick(startpos.mResultContent,
|
|
|
|
startpos.mContentOffset, startpos.mContentOffset,
|
|
|
|
PR_FALSE, aMultipleSelection,
|
|
|
|
nsFrameSelection::HINTRIGHT);
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2008-10-17 19:46:33 +00:00
|
|
|
|
|
|
|
rv = frameSelection->HandleClick(endpos.mResultContent,
|
|
|
|
endpos.mContentOffset, endpos.mContentOffset,
|
|
|
|
PR_TRUE, PR_FALSE,
|
|
|
|
nsFrameSelection::HINTLEFT);
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2003-07-21 19:51:34 +00:00
|
|
|
// maintain selection
|
2007-09-15 19:48:20 +00:00
|
|
|
return frameSelection->MaintainSelection(aAmountBack);
|
1999-05-17 00:21:18 +00:00
|
|
|
}
|
|
|
|
|
2004-07-31 23:15:21 +00:00
|
|
|
NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
|
1999-09-15 20:38:42 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-27 16:44:52 +00:00
|
|
|
{
|
2000-08-08 23:48:42 +00:00
|
|
|
PRBool selectable;
|
2004-08-29 03:08:44 +00:00
|
|
|
PRUint8 selectStyle;
|
|
|
|
IsSelectable(&selectable, &selectStyle);
|
2005-12-07 23:08:39 +00:00
|
|
|
// XXX Do we really need to exclude non-selectable content here?
|
2008-09-06 08:52:56 +00:00
|
|
|
// GetContentOffsetsFromPoint can handle it just fine, although some
|
2005-12-07 23:08:39 +00:00
|
|
|
// other stuff might not like it.
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable)
|
2000-05-16 13:52:28 +00:00
|
|
|
return NS_OK;
|
|
|
|
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
|
1998-12-14 18:34:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2003-12-21 05:36:36 +00:00
|
|
|
nsIPresShell *presShell = aPresContext->PresShell();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2006-09-18 08:47:06 +00:00
|
|
|
nsCOMPtr<nsFrameSelection> frameselection = GetFrameSelection();
|
2006-04-26 02:01:07 +00:00
|
|
|
PRBool mouseDown = frameselection->GetMouseDownState();
|
|
|
|
if (!mouseDown)
|
2006-02-21 00:49:04 +00:00
|
|
|
return NS_OK;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
2004-08-29 03:08:44 +00:00
|
|
|
frameselection->StopAutoScrollTimer();
|
2006-09-18 08:47:06 +00:00
|
|
|
|
2004-08-29 03:08:44 +00:00
|
|
|
// Check if we are dragging in a table cell
|
|
|
|
nsCOMPtr<nsIContent> parentContent;
|
|
|
|
PRInt32 contentOffset;
|
|
|
|
PRInt32 target;
|
|
|
|
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
2006-02-21 00:49:04 +00:00
|
|
|
nsresult result;
|
2004-08-29 03:08:44 +00:00
|
|
|
result = GetDataForTableSelection(frameselection, presShell, me,
|
|
|
|
getter_AddRefs(parentContent),
|
|
|
|
&contentOffset, &target);
|
|
|
|
|
2005-08-23 03:57:07 +00:00
|
|
|
if (NS_SUCCEEDED(result) && parentContent) {
|
2004-08-29 03:08:44 +00:00
|
|
|
frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
2005-08-23 03:57:07 +00:00
|
|
|
} else {
|
2005-09-04 20:04:23 +00:00
|
|
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
2006-04-26 02:01:07 +00:00
|
|
|
frameselection->HandleDrag(this, pt);
|
2005-08-23 03:57:07 +00:00
|
|
|
}
|
2004-08-29 03:08:44 +00:00
|
|
|
|
2009-09-13 13:13:16 +00:00
|
|
|
// get the nearest scrollframe
|
|
|
|
nsIFrame* checkFrame = this;
|
|
|
|
nsIScrollableFrame *scrollFrame = nsnull;
|
|
|
|
while (checkFrame) {
|
|
|
|
scrollFrame = do_QueryFrame(checkFrame);
|
|
|
|
if (scrollFrame) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
checkFrame = checkFrame->GetParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scrollFrame) {
|
|
|
|
nsIView* capturingView = scrollFrame->GetScrollableView()->View();
|
|
|
|
if (capturingView) {
|
2006-09-18 08:47:06 +00:00
|
|
|
// Get the view that aEvent->point is relative to. This is disgusting.
|
|
|
|
nsIView* eventView = nsnull;
|
|
|
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(aEvent, this,
|
|
|
|
&eventView);
|
2009-09-13 13:13:16 +00:00
|
|
|
nsPoint capturePt = pt + eventView->GetOffsetTo(capturingView);
|
|
|
|
frameselection->StartAutoScrollTimer(capturingView, capturePt, 30);
|
2006-09-18 08:47:06 +00:00
|
|
|
}
|
1998-12-14 18:34:14 +00:00
|
|
|
}
|
2009-09-13 13:13:16 +00:00
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-05-12 06:40:49 +00:00
|
|
|
/**
|
|
|
|
* This static method handles part of the nsFrame::HandleRelease in a way
|
|
|
|
* which doesn't rely on the nsFrame object to stay alive.
|
|
|
|
*/
|
|
|
|
static nsresult
|
|
|
|
HandleFrameSelection(nsFrameSelection* aFrameSelection,
|
|
|
|
nsIFrame::ContentOffsets& aOffsets,
|
|
|
|
PRBool aHandleTableSel,
|
2006-08-04 07:35:35 +00:00
|
|
|
PRInt32 aContentOffsetForTableSel,
|
|
|
|
PRInt32 aTargetForTableSel,
|
2006-05-12 06:40:49 +00:00
|
|
|
nsIContent* aParentContentForTableSel,
|
|
|
|
nsGUIEvent* aEvent,
|
|
|
|
nsEventStatus* aEventStatus)
|
|
|
|
{
|
|
|
|
if (!aFrameSelection) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
|
|
|
|
if (!aHandleTableSel) {
|
|
|
|
nsMouseEvent *me = aFrameSelection->GetDelayedCaretData();
|
|
|
|
if (!aOffsets.content || !me) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We are doing this to simulate what we would have done on HandlePress.
|
|
|
|
// We didn't do it there to give the user an opportunity to drag
|
|
|
|
// the text, but since they didn't drag, we want to place the
|
|
|
|
// caret.
|
|
|
|
// However, we'll use the mouse position from the release, since:
|
|
|
|
// * it's easier
|
|
|
|
// * that's the normal click position to use (although really, in
|
|
|
|
// the normal case, small movements that don't count as a drag
|
|
|
|
// can do selection)
|
|
|
|
aFrameSelection->SetMouseDownState(PR_TRUE);
|
|
|
|
|
|
|
|
rv = aFrameSelection->HandleClick(aOffsets.content,
|
|
|
|
aOffsets.StartOffset(),
|
|
|
|
aOffsets.EndOffset(),
|
|
|
|
me->isShift, PR_FALSE,
|
|
|
|
aOffsets.associateWithNext);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
} else if (aParentContentForTableSel) {
|
|
|
|
aFrameSelection->SetMouseDownState(PR_FALSE);
|
|
|
|
rv = aFrameSelection->HandleTableSelection(aParentContentForTableSel,
|
|
|
|
aContentOffsetForTableSel,
|
|
|
|
aTargetForTableSel,
|
|
|
|
(nsMouseEvent *)aEvent);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aFrameSelection->SetDelayedCaretData(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
aFrameSelection->SetMouseDownState(PR_FALSE);
|
|
|
|
aFrameSelection->StopAutoScrollTimer();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
|
|
|
|
nsGUIEvent* aEvent,
|
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-27 16:44:52 +00:00
|
|
|
{
|
2009-09-13 13:13:16 +00:00
|
|
|
nsIFrame* activeFrame = GetActiveSelectionFrame(aPresContext, this);
|
2005-03-07 00:34:44 +00:00
|
|
|
|
|
|
|
// We can unconditionally stop capturing because
|
|
|
|
// we should never be capturing when the mouse button is up
|
2009-09-13 13:13:16 +00:00
|
|
|
nsIPresShell::SetCapturingContent(nsnull, 0);
|
2005-03-07 00:34:44 +00:00
|
|
|
|
2006-05-12 06:40:49 +00:00
|
|
|
PRBool selectionOff =
|
|
|
|
(DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF);
|
2000-04-13 00:15:02 +00:00
|
|
|
|
2006-05-12 06:40:49 +00:00
|
|
|
nsRefPtr<nsFrameSelection> frameselection;
|
|
|
|
ContentOffsets offsets;
|
|
|
|
nsCOMPtr<nsIContent> parentContent;
|
|
|
|
PRInt32 contentOffsetForTableSel = 0;
|
|
|
|
PRInt32 targetForTableSel = 0;
|
|
|
|
PRBool handleTableSelection = PR_TRUE;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2006-05-12 06:40:49 +00:00
|
|
|
if (!selectionOff) {
|
|
|
|
frameselection = GetFrameSelection();
|
2006-12-16 14:40:44 +00:00
|
|
|
if (nsEventStatus_eConsumeNoDefault != *aEventStatus && frameselection) {
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
// Check if the frameselection recorded the mouse going down.
|
|
|
|
// If not, the user must have clicked in a part of the selection.
|
|
|
|
// Place the caret before continuing!
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2006-04-26 02:01:07 +00:00
|
|
|
PRBool mouseDown = frameselection->GetMouseDownState();
|
|
|
|
nsMouseEvent *me = frameselection->GetDelayedCaretData();
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2006-05-12 06:40:49 +00:00
|
|
|
if (!mouseDown && me && me->clickCount < 2) {
|
2005-12-16 04:58:33 +00:00
|
|
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
2006-05-12 06:40:49 +00:00
|
|
|
offsets = GetContentOffsetsFromPoint(pt);
|
|
|
|
handleTableSelection = PR_FALSE;
|
|
|
|
} else {
|
2007-03-30 21:11:41 +00:00
|
|
|
GetDataForTableSelection(frameselection, PresContext()->PresShell(),
|
2006-05-12 06:40:49 +00:00
|
|
|
(nsMouseEvent *)aEvent,
|
|
|
|
getter_AddRefs(parentContent),
|
|
|
|
&contentOffsetForTableSel,
|
|
|
|
&targetForTableSel);
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
}
|
2000-05-08 03:59:53 +00:00
|
|
|
}
|
2000-05-25 20:04:02 +00:00
|
|
|
}
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2006-05-12 06:40:49 +00:00
|
|
|
// We might be capturing in some other document and the event just happened to
|
|
|
|
// trickle down here. Make sure that document's frame selection is notified.
|
|
|
|
// Note, this may cause the current nsFrame object to be deleted, bug 336592.
|
|
|
|
if (activeFrame != this &&
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<nsFrame*>(activeFrame)->DisplaySelection(activeFrame->PresContext())
|
2006-05-12 06:40:49 +00:00
|
|
|
!= nsISelectionController::SELECTION_OFF) {
|
|
|
|
nsRefPtr<nsFrameSelection> frameSelection =
|
|
|
|
activeFrame->GetFrameSelection();
|
|
|
|
frameSelection->SetMouseDownState(PR_FALSE);
|
|
|
|
frameSelection->StopAutoScrollTimer();
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
|
|
|
|
2006-05-12 06:40:49 +00:00
|
|
|
// Do not call any methods of the current object after this point!!!
|
|
|
|
// The object is perhaps dead!
|
|
|
|
|
|
|
|
return selectionOff
|
|
|
|
? NS_OK
|
|
|
|
: HandleFrameSelection(frameselection, offsets, handleTableSelection,
|
|
|
|
contentOffsetForTableSel, targetForTableSel,
|
|
|
|
parentContent, aEvent, aEventStatus);
|
1998-04-27 16:44:52 +00:00
|
|
|
}
|
|
|
|
|
2008-07-01 19:16:45 +00:00
|
|
|
struct NS_STACK_CLASS FrameContentRange {
|
2006-02-27 05:57:37 +00:00
|
|
|
FrameContentRange(nsIContent* aContent, PRInt32 aStart, PRInt32 aEnd) :
|
2005-12-07 23:08:39 +00:00
|
|
|
content(aContent), start(aStart), end(aEnd) { }
|
|
|
|
nsCOMPtr<nsIContent> content;
|
|
|
|
PRInt32 start;
|
|
|
|
PRInt32 end;
|
|
|
|
};
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
// Retrieve the content offsets of a frame
|
2006-02-27 05:57:37 +00:00
|
|
|
static FrameContentRange GetRangeForFrame(nsIFrame* aFrame) {
|
2005-12-07 23:08:39 +00:00
|
|
|
nsCOMPtr<nsIContent> content, parent;
|
|
|
|
content = aFrame->GetContent();
|
2005-12-25 19:01:45 +00:00
|
|
|
if (!content) {
|
|
|
|
NS_WARNING("Frame has no content");
|
2006-02-27 05:57:37 +00:00
|
|
|
return FrameContentRange(nsnull, -1, -1);
|
2005-12-25 19:01:45 +00:00
|
|
|
}
|
2005-12-20 09:13:47 +00:00
|
|
|
nsIAtom* type = aFrame->GetType();
|
2006-12-26 17:47:52 +00:00
|
|
|
if (type == nsGkAtoms::textFrame) {
|
2005-12-07 23:08:39 +00:00
|
|
|
PRInt32 offset, offsetEnd;
|
|
|
|
aFrame->GetOffsets(offset, offsetEnd);
|
2006-02-27 05:57:37 +00:00
|
|
|
return FrameContentRange(content, offset, offsetEnd);
|
2005-12-07 23:08:39 +00:00
|
|
|
}
|
2006-12-26 17:47:52 +00:00
|
|
|
if (type == nsGkAtoms::brFrame) {
|
2005-12-20 09:13:47 +00:00
|
|
|
parent = content->GetParent();
|
|
|
|
PRInt32 beginOffset = parent->IndexOf(content);
|
2006-02-27 05:57:37 +00:00
|
|
|
return FrameContentRange(parent, beginOffset, beginOffset);
|
2005-12-20 09:13:47 +00:00
|
|
|
}
|
2005-12-07 23:08:39 +00:00
|
|
|
// Loop to deal with anonymous content, which has no index; this loop
|
|
|
|
// probably won't run more than twice under normal conditions
|
|
|
|
do {
|
|
|
|
parent = content->GetParent();
|
|
|
|
if (parent) {
|
|
|
|
PRInt32 beginOffset = parent->IndexOf(content);
|
|
|
|
if (beginOffset >= 0)
|
2006-02-27 05:57:37 +00:00
|
|
|
return FrameContentRange(parent, beginOffset, beginOffset + 1);
|
2005-12-07 23:08:39 +00:00
|
|
|
content = parent;
|
|
|
|
}
|
|
|
|
} while (parent);
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
// The root content node must act differently
|
2006-02-27 05:57:37 +00:00
|
|
|
return FrameContentRange(content, 0, content->GetChildCount());
|
2005-12-07 23:08:39 +00:00
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
// The FrameTarget represents the closest frame to a point that can be selected
|
|
|
|
// The frame is the frame represented, frameEdge says whether one end of the
|
|
|
|
// frame is the result (in which case different handling is needed), and
|
|
|
|
// afterFrame says which end is repersented if frameEdge is true
|
|
|
|
struct FrameTarget {
|
|
|
|
FrameTarget(nsIFrame* aFrame, PRBool aFrameEdge, PRBool aAfterFrame) :
|
|
|
|
frame(aFrame), frameEdge(aFrameEdge), afterFrame(aAfterFrame) { }
|
|
|
|
static FrameTarget Null() {
|
|
|
|
return FrameTarget(nsnull, PR_FALSE, PR_FALSE);
|
|
|
|
}
|
|
|
|
PRBool IsNull() {
|
|
|
|
return !frame;
|
|
|
|
}
|
|
|
|
nsIFrame* frame;
|
|
|
|
PRPackedBool frameEdge;
|
|
|
|
PRPackedBool afterFrame;
|
|
|
|
};
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
// See function implementation for information
|
|
|
|
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint);
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
static PRBool SelfIsSelectable(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
return !(aFrame->IsGeneratedContentFrame() ||
|
|
|
|
aFrame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_NONE);
|
|
|
|
}
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
static PRBool SelectionDescendToKids(nsIFrame* aFrame) {
|
|
|
|
PRUint8 style = aFrame->GetStyleUIReset()->mUserSelect;
|
|
|
|
nsIFrame* parent = aFrame->GetParent();
|
|
|
|
// If we are only near (not directly over) then don't traverse
|
|
|
|
// frames with independent selection (e.g. text and list controls)
|
|
|
|
// unless we're already inside such a frame (see bug 268497). Note that this
|
|
|
|
// prevents any of the users of this method from entering form controls.
|
|
|
|
// XXX We might want some way to allow using the up-arrow to go into a form
|
|
|
|
// control, but the focus didn't work right anyway; it'd probably be enough
|
|
|
|
// if the left and right arrows could enter textboxes (which I don't believe
|
|
|
|
// they can at the moment)
|
|
|
|
return !aFrame->IsGeneratedContentFrame() &&
|
|
|
|
style != NS_STYLE_USER_SELECT_ALL &&
|
|
|
|
style != NS_STYLE_USER_SELECT_NONE &&
|
|
|
|
((parent->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) ||
|
|
|
|
!(aFrame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION));
|
|
|
|
}
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
static FrameTarget GetSelectionClosestFrameForChild(nsIFrame* aChild,
|
|
|
|
nsPoint aPoint)
|
|
|
|
{
|
|
|
|
nsIFrame* parent = aChild->GetParent();
|
|
|
|
if (SelectionDescendToKids(aChild)) {
|
|
|
|
nsPoint pt = aPoint - aChild->GetOffsetTo(parent);
|
|
|
|
return GetSelectionClosestFrame(aChild, pt);
|
|
|
|
}
|
|
|
|
return FrameTarget(aChild, PR_FALSE, PR_FALSE);
|
|
|
|
}
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
// When the cursor needs to be at the beginning of a block, it shouldn't be
|
|
|
|
// before the first child. A click on a block whose first child is a block
|
|
|
|
// should put the cursor in the child. The cursor shouldn't be between the
|
|
|
|
// blocks, because that's not where it's expected.
|
|
|
|
// Note that this method is guaranteed to succeed.
|
|
|
|
static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame,
|
|
|
|
PRBool aEndFrame) {
|
|
|
|
if (SelectionDescendToKids(aFrame)) {
|
|
|
|
nsIFrame* result = nsnull;
|
|
|
|
nsIFrame *frame = aFrame->GetFirstChild(nsnull);
|
|
|
|
if (!aEndFrame) {
|
|
|
|
while (frame && (!SelfIsSelectable(frame) ||
|
|
|
|
frame->IsEmpty()))
|
|
|
|
frame = frame->GetNextSibling();
|
|
|
|
if (frame)
|
|
|
|
result = frame;
|
|
|
|
} else {
|
|
|
|
// Because the frame tree is singly linked, to find the last frame,
|
|
|
|
// we have to iterate through all the frames
|
|
|
|
// XXX I have a feeling this could be slow for long blocks, although
|
|
|
|
// I can't find any slowdowns
|
|
|
|
while (frame) {
|
|
|
|
if (!frame->IsEmpty() && SelfIsSelectable(frame))
|
|
|
|
result = frame;
|
|
|
|
frame = frame->GetNextSibling();
|
1999-11-18 19:40:52 +00:00
|
|
|
}
|
2005-12-07 23:08:39 +00:00
|
|
|
}
|
|
|
|
if (result)
|
|
|
|
return DrillDownToSelectionFrame(result, aEndFrame);
|
|
|
|
}
|
|
|
|
// If the current frame has no targetable children, target the current frame
|
|
|
|
return FrameTarget(aFrame, PR_TRUE, aEndFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This method finds the closest valid FrameTarget on a given line; if there is
|
|
|
|
// no valid FrameTarget on the line, it returns a null FrameTarget
|
|
|
|
static FrameTarget GetSelectionClosestFrameForLine(
|
|
|
|
nsBlockFrame* aParent,
|
|
|
|
nsBlockFrame::line_iterator aLine,
|
|
|
|
nsPoint aPoint)
|
|
|
|
{
|
|
|
|
nsIFrame *frame = aLine->mFirstChild;
|
|
|
|
// Account for end of lines (any iterator from the block is valid)
|
|
|
|
if (aLine == aParent->end_lines())
|
|
|
|
return DrillDownToSelectionFrame(aParent, PR_TRUE);
|
|
|
|
nsIFrame *closestFromLeft = nsnull, *closestFromRight = nsnull;
|
|
|
|
nsRect rect = aLine->mBounds;
|
|
|
|
nscoord closestLeft = rect.x, closestRight = rect.XMost();
|
|
|
|
for (PRInt32 n = aLine->GetChildCount(); n;
|
|
|
|
--n, frame = frame->GetNextSibling()) {
|
|
|
|
if (!SelfIsSelectable(frame) || frame->IsEmpty())
|
|
|
|
continue;
|
|
|
|
nsRect frameRect = frame->GetRect();
|
|
|
|
if (aPoint.x >= frameRect.x) {
|
|
|
|
if (aPoint.x < frameRect.XMost()) {
|
|
|
|
return GetSelectionClosestFrameForChild(frame, aPoint);
|
|
|
|
}
|
|
|
|
if (frameRect.XMost() >= closestLeft) {
|
|
|
|
closestFromLeft = frame;
|
|
|
|
closestLeft = frameRect.XMost();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (frameRect.x <= closestRight) {
|
|
|
|
closestFromRight = frame;
|
|
|
|
closestRight = frameRect.x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!closestFromLeft && !closestFromRight) {
|
|
|
|
// We should only get here if there are no selectable frames on a line
|
|
|
|
// XXX Do we need more elaborate handling here?
|
|
|
|
return FrameTarget::Null();
|
|
|
|
}
|
|
|
|
if (closestFromLeft &&
|
|
|
|
(!closestFromRight ||
|
|
|
|
(abs(aPoint.x - closestLeft) <= abs(aPoint.x - closestRight)))) {
|
|
|
|
return GetSelectionClosestFrameForChild(closestFromLeft, aPoint);
|
|
|
|
}
|
|
|
|
return GetSelectionClosestFrameForChild(closestFromRight, aPoint);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This method is for the special handling we do for block frames; they're
|
|
|
|
// special because they represent paragraphs and because they are organized
|
|
|
|
// into lines, which have bounds that are not stored elsewhere in the
|
|
|
|
// frame tree. Returns a null FrameTarget for frames which are not
|
|
|
|
// blocks or blocks with no lines.
|
|
|
|
static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
|
|
|
nsPoint aPoint)
|
|
|
|
{
|
2008-07-13 22:10:23 +00:00
|
|
|
nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(aFrame); // used only for QI
|
|
|
|
if (!bf)
|
2005-12-07 23:08:39 +00:00
|
|
|
return FrameTarget::Null();
|
|
|
|
|
|
|
|
// This code searches for the correct line
|
|
|
|
nsBlockFrame::line_iterator firstLine = bf->begin_lines();
|
|
|
|
nsBlockFrame::line_iterator end = bf->end_lines();
|
|
|
|
if (firstLine == end)
|
|
|
|
return FrameTarget::Null();
|
|
|
|
nsBlockFrame::line_iterator curLine = firstLine;
|
|
|
|
nsBlockFrame::line_iterator closestLine = end;
|
|
|
|
while (curLine != end) {
|
|
|
|
// Check to see if our point lies with the line's Y bounds
|
|
|
|
nscoord y = aPoint.y - curLine->mBounds.y;
|
|
|
|
nscoord height = curLine->mBounds.height;
|
|
|
|
if (y >= 0 && y < height) {
|
|
|
|
closestLine = curLine;
|
|
|
|
break; // We found the line; stop looking
|
|
|
|
}
|
|
|
|
if (y < 0)
|
|
|
|
break;
|
|
|
|
++curLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (closestLine == end) {
|
|
|
|
nsBlockFrame::line_iterator prevLine = curLine.prev();
|
|
|
|
nsBlockFrame::line_iterator nextLine = curLine;
|
|
|
|
// Avoid empty lines
|
|
|
|
while (nextLine != end && nextLine->IsEmpty())
|
|
|
|
++nextLine;
|
|
|
|
while (prevLine != end && prevLine->IsEmpty())
|
|
|
|
--prevLine;
|
|
|
|
|
|
|
|
// This hidden pref dictates whether a point above or below all lines comes
|
|
|
|
// up with a line or the beginning or end of the frame; 0 on Windows,
|
|
|
|
// 1 on other platforms by default at the writing of this code
|
|
|
|
PRInt32 dragOutOfFrame =
|
|
|
|
nsContentUtils::GetIntPref("browser.drag_out_of_frame_style");
|
|
|
|
|
|
|
|
if (prevLine == end) {
|
|
|
|
if (dragOutOfFrame == 1 || nextLine == end)
|
|
|
|
return DrillDownToSelectionFrame(aFrame, PR_FALSE);
|
|
|
|
closestLine = nextLine;
|
|
|
|
} else if (nextLine == end) {
|
|
|
|
if (dragOutOfFrame == 1)
|
|
|
|
return DrillDownToSelectionFrame(aFrame, PR_TRUE);
|
|
|
|
closestLine = prevLine;
|
|
|
|
} else { // Figure out which line is closer
|
|
|
|
if (aPoint.y - prevLine->mBounds.YMost() < nextLine->mBounds.y - aPoint.y)
|
|
|
|
closestLine = prevLine;
|
|
|
|
else
|
|
|
|
closestLine = nextLine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
FrameTarget target = GetSelectionClosestFrameForLine(bf, closestLine,
|
|
|
|
aPoint);
|
|
|
|
if (!target.IsNull())
|
|
|
|
return target;
|
|
|
|
++closestLine;
|
|
|
|
} while (closestLine != end);
|
|
|
|
// Fall back to just targeting the last targetable place
|
|
|
|
return DrillDownToSelectionFrame(aFrame, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetSelectionClosestFrame is the helper function that calculates the closest
|
|
|
|
// frame to the given point.
|
|
|
|
// It doesn't completely account for offset styles, so needs to be used in
|
|
|
|
// restricted environments.
|
2006-08-28 20:12:37 +00:00
|
|
|
// Cannot handle overlapping frames correctly, so it should receive the output
|
2005-12-07 23:08:39 +00:00
|
|
|
// of GetFrameForPoint
|
|
|
|
// Guaranteed to return a valid FrameTarget
|
|
|
|
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Handle blocks; if the frame isn't a block, the method fails
|
|
|
|
FrameTarget target = GetSelectionClosestFrameForBlock(aFrame, aPoint);
|
|
|
|
if (!target.IsNull())
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame *kid = aFrame->GetFirstChild(nsnull);
|
|
|
|
|
|
|
|
if (kid) {
|
|
|
|
// Go through all the child frames to find the closest one
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
// Large number to force the comparison to succeed
|
|
|
|
const nscoord HUGE_DISTANCE = nscoord_MAX;
|
|
|
|
nscoord closestXDistance = HUGE_DISTANCE;
|
|
|
|
nscoord closestYDistance = HUGE_DISTANCE;
|
|
|
|
nsIFrame *closestFrame = nsnull;
|
|
|
|
|
2006-03-01 21:18:30 +00:00
|
|
|
for (; kid; kid = kid->GetNextSibling()) {
|
2005-12-07 23:08:39 +00:00
|
|
|
if (!SelfIsSelectable(kid) || kid->IsEmpty())
|
|
|
|
continue;
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsRect rect = kid->GetRect();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
nscoord fromLeft = aPoint.x - rect.x;
|
|
|
|
nscoord fromRight = aPoint.x - rect.XMost();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
nscoord xDistance;
|
|
|
|
if (fromLeft >= 0 && fromRight <= 0) {
|
|
|
|
xDistance = 0;
|
|
|
|
} else {
|
2009-09-16 15:01:36 +00:00
|
|
|
xDistance = NS_MIN(abs(fromLeft), abs(fromRight));
|
2005-12-07 23:08:39 +00:00
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
if (xDistance <= closestXDistance)
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
2005-12-07 23:08:39 +00:00
|
|
|
if (xDistance < closestXDistance)
|
|
|
|
closestYDistance = HUGE_DISTANCE;
|
2001-08-26 18:33:57 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
nscoord fromTop = aPoint.y - rect.y;
|
|
|
|
nscoord fromBottom = aPoint.y - rect.YMost();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
nscoord yDistance;
|
|
|
|
if (fromTop >= 0 && fromBottom <= 0)
|
|
|
|
yDistance = 0;
|
2001-08-26 18:33:57 +00:00
|
|
|
else
|
2009-09-16 15:01:36 +00:00
|
|
|
yDistance = NS_MIN(abs(fromTop), abs(fromBottom));
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
if (yDistance < closestYDistance)
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
2005-12-07 23:08:39 +00:00
|
|
|
closestXDistance = xDistance;
|
|
|
|
closestYDistance = yDistance;
|
1999-09-29 20:04:05 +00:00
|
|
|
closestFrame = kid;
|
|
|
|
}
|
|
|
|
}
|
2006-03-01 21:18:30 +00:00
|
|
|
}
|
2005-12-08 18:09:17 +00:00
|
|
|
if (closestFrame)
|
2005-12-07 23:08:39 +00:00
|
|
|
return GetSelectionClosestFrameForChild(closestFrame, aPoint);
|
2000-10-28 22:17:53 +00:00
|
|
|
}
|
2005-12-07 23:08:39 +00:00
|
|
|
return FrameTarget(aFrame, PR_FALSE, PR_FALSE);
|
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2006-02-27 05:57:37 +00:00
|
|
|
nsIFrame::ContentOffsets OffsetsForSingleFrame(nsIFrame* aFrame, nsPoint aPoint)
|
2005-12-07 23:08:39 +00:00
|
|
|
{
|
2006-02-27 05:57:37 +00:00
|
|
|
nsIFrame::ContentOffsets offsets;
|
|
|
|
FrameContentRange range = GetRangeForFrame(aFrame);
|
|
|
|
offsets.content = range.content;
|
|
|
|
// If there are continuations (meaning it's not one rectangle), this is the
|
|
|
|
// best this function can do
|
|
|
|
if (aFrame->GetNextContinuation() || aFrame->GetPrevContinuation()) {
|
|
|
|
offsets.offset = range.start;
|
|
|
|
offsets.secondaryOffset = range.end;
|
|
|
|
offsets.associateWithNext = PR_TRUE;
|
|
|
|
return offsets;
|
|
|
|
}
|
2000-08-08 23:48:42 +00:00
|
|
|
|
2006-02-27 05:57:37 +00:00
|
|
|
// Figure out whether the offsets should be over, after, or before the frame
|
|
|
|
nsRect rect(nsPoint(0, 0), aFrame->GetSize());
|
|
|
|
|
|
|
|
PRBool isBlock = (aFrame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE);
|
|
|
|
PRBool isRtl = (aFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL);
|
|
|
|
if ((isBlock && rect.y < aPoint.y) ||
|
|
|
|
(!isBlock && ((isRtl && rect.x + rect.width / 2 > aPoint.x) ||
|
|
|
|
(!isRtl && rect.x + rect.width / 2 < aPoint.x)))) {
|
|
|
|
offsets.offset = range.end;
|
|
|
|
if (rect.Contains(aPoint))
|
|
|
|
offsets.secondaryOffset = range.start;
|
|
|
|
else
|
|
|
|
offsets.secondaryOffset = range.end;
|
|
|
|
} else {
|
|
|
|
offsets.offset = range.start;
|
|
|
|
if (rect.Contains(aPoint))
|
|
|
|
offsets.secondaryOffset = range.end;
|
|
|
|
else
|
|
|
|
offsets.secondaryOffset = range.start;
|
|
|
|
}
|
|
|
|
offsets.associateWithNext = (offsets.offset == range.start);
|
|
|
|
return offsets;
|
|
|
|
}
|
|
|
|
|
2006-03-13 01:13:25 +00:00
|
|
|
static nsIFrame* AdjustFrameForSelectionStyles(nsIFrame* aFrame) {
|
|
|
|
nsIFrame* adjustedFrame = aFrame;
|
|
|
|
for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent())
|
2005-12-07 23:08:39 +00:00
|
|
|
{
|
|
|
|
// These are the conditions that make all children not able to handle
|
|
|
|
// a cursor.
|
|
|
|
if (frame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_NONE ||
|
|
|
|
frame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_ALL ||
|
|
|
|
frame->IsGeneratedContentFrame()) {
|
|
|
|
adjustedFrame = frame;
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
2005-12-07 23:08:39 +00:00
|
|
|
}
|
2006-03-13 01:13:25 +00:00
|
|
|
return adjustedFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-02 19:33:49 +00:00
|
|
|
nsIFrame::ContentOffsets nsIFrame::GetContentOffsetsFromPoint(nsPoint aPoint,
|
|
|
|
PRBool aIgnoreSelectionStyle)
|
|
|
|
{
|
|
|
|
nsIFrame *adjustedFrame;
|
|
|
|
if (aIgnoreSelectionStyle) {
|
|
|
|
adjustedFrame = this;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// This section of code deals with special selection styles. Note that
|
|
|
|
// -moz-none and -moz-all exist, even though they don't need to be explicitly
|
|
|
|
// handled.
|
|
|
|
// The offset is forced not to end up in generated content; content offsets
|
|
|
|
// cannot represent content outside of the document's content tree.
|
|
|
|
|
|
|
|
adjustedFrame = AdjustFrameForSelectionStyles(this);
|
|
|
|
|
|
|
|
// -moz-user-select: all needs special handling, because clicking on it
|
|
|
|
// should lead to the whole frame being selected
|
|
|
|
if (adjustedFrame && adjustedFrame->GetStyleUIReset()->mUserSelect ==
|
|
|
|
NS_STYLE_USER_SELECT_ALL) {
|
|
|
|
return OffsetsForSingleFrame(adjustedFrame, aPoint +
|
2006-02-27 05:57:37 +00:00
|
|
|
this->GetOffsetTo(adjustedFrame));
|
2006-10-02 19:33:49 +00:00
|
|
|
}
|
2006-02-27 05:57:37 +00:00
|
|
|
|
2006-10-02 19:33:49 +00:00
|
|
|
// For other cases, try to find a closest frame starting from the parent of
|
|
|
|
// the unselectable frame
|
|
|
|
if (adjustedFrame != this)
|
|
|
|
adjustedFrame = adjustedFrame->GetParent();
|
|
|
|
}
|
2005-12-07 23:08:39 +00:00
|
|
|
|
|
|
|
nsPoint adjustedPoint = aPoint + this->GetOffsetTo(adjustedFrame);
|
2006-10-02 19:33:49 +00:00
|
|
|
|
2005-12-07 23:08:39 +00:00
|
|
|
FrameTarget closest = GetSelectionClosestFrame(adjustedFrame, adjustedPoint);
|
|
|
|
|
|
|
|
// If the correct offset is at one end of a frame, use offset-based
|
|
|
|
// calculation method
|
|
|
|
if (closest.frameEdge) {
|
2006-02-27 05:57:37 +00:00
|
|
|
ContentOffsets offsets;
|
|
|
|
FrameContentRange range = GetRangeForFrame(closest.frame);
|
|
|
|
offsets.content = range.content;
|
|
|
|
if (closest.afterFrame)
|
|
|
|
offsets.offset = range.end;
|
|
|
|
else
|
|
|
|
offsets.offset = range.start;
|
|
|
|
offsets.secondaryOffset = offsets.offset;
|
|
|
|
offsets.associateWithNext = (offsets.offset == range.start);
|
|
|
|
return offsets;
|
2005-12-07 23:08:39 +00:00
|
|
|
}
|
|
|
|
nsPoint pt = aPoint - closest.frame->GetOffsetTo(this);
|
2007-07-08 07:08:04 +00:00
|
|
|
return static_cast<nsFrame*>(closest.frame)->CalcContentOffsetsFromFramePoint(pt);
|
2005-12-07 23:08:39 +00:00
|
|
|
|
|
|
|
// XXX should I add some kind of offset standardization?
|
|
|
|
// consider <b>xxxxx</b><i>zzzzz</i>; should any click between the last
|
|
|
|
// x and first z put the cursor in the same logical position in addition
|
|
|
|
// to the same visual position?
|
|
|
|
}
|
|
|
|
|
2006-02-27 05:57:37 +00:00
|
|
|
nsIFrame::ContentOffsets nsFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint)
|
2005-12-07 23:08:39 +00:00
|
|
|
{
|
2006-02-27 05:57:37 +00:00
|
|
|
return OffsetsForSingleFrame(this, aPoint);
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
|
|
|
|
1998-11-18 05:25:26 +00:00
|
|
|
NS_IMETHODIMP
|
2004-12-30 21:56:11 +00:00
|
|
|
nsFrame::GetCursor(const nsPoint& aPoint,
|
|
|
|
nsIFrame::Cursor& aCursor)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2004-12-30 21:56:11 +00:00
|
|
|
FillCursorInformationFromStyle(GetStyleUserInterface(), aCursor);
|
|
|
|
if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) {
|
|
|
|
aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
|
1998-11-18 02:11:54 +00:00
|
|
|
}
|
2004-12-30 21:56:11 +00:00
|
|
|
|
|
|
|
|
1998-11-18 05:25:26 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Resize and incremental reflow
|
1998-05-14 00:47:32 +00:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
/* virtual */ void
|
|
|
|
nsFrame::MarkIntrinsicWidthsDirty()
|
|
|
|
{
|
|
|
|
// This version is meant only for what used to be box-to-block adaptors.
|
|
|
|
// It should not be called by other derived classes.
|
|
|
|
if (IsBoxWrapped()) {
|
|
|
|
nsBoxLayoutMetrics *metrics = BoxMetrics();
|
|
|
|
|
|
|
|
SizeNeedsRecalc(metrics->mPrefSize);
|
|
|
|
SizeNeedsRecalc(metrics->mMinSize);
|
|
|
|
SizeNeedsRecalc(metrics->mMaxSize);
|
|
|
|
SizeNeedsRecalc(metrics->mBlockPrefSize);
|
|
|
|
SizeNeedsRecalc(metrics->mBlockMinSize);
|
|
|
|
CoordNeedsRecalc(metrics->mFlex);
|
|
|
|
CoordNeedsRecalc(metrics->mAscent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nscoord
|
|
|
|
nsFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
|
|
|
{
|
|
|
|
nscoord result = 0;
|
|
|
|
DISPLAY_MIN_WIDTH(this, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nscoord
|
|
|
|
nsFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
|
|
|
{
|
|
|
|
nscoord result = 0;
|
|
|
|
DISPLAY_PREF_WIDTH(this, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
nsFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
|
|
|
nsIFrame::InlineMinWidthData *aData)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(GetParent(), "Must have a parent if we get here!");
|
|
|
|
PRBool canBreak = !CanContinueTextRun() &&
|
|
|
|
GetParent()->GetStyleText()->WhiteSpaceCanWrap();
|
|
|
|
|
|
|
|
if (canBreak)
|
2007-06-21 22:32:47 +00:00
|
|
|
aData->OptionallyBreak(aRenderingContext);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
aData->trailingWhitespace = 0;
|
|
|
|
aData->skipWhitespace = PR_FALSE;
|
|
|
|
aData->trailingTextFrame = nsnull;
|
|
|
|
aData->currentLine += nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
|
|
|
this, nsLayoutUtils::MIN_WIDTH);
|
2007-06-21 22:32:47 +00:00
|
|
|
aData->atStartOfLine = PR_FALSE;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (canBreak)
|
2007-06-21 22:32:47 +00:00
|
|
|
aData->OptionallyBreak(aRenderingContext);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
nsFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
|
|
|
nsIFrame::InlinePrefWidthData *aData)
|
|
|
|
{
|
|
|
|
aData->trailingWhitespace = 0;
|
|
|
|
aData->skipWhitespace = PR_FALSE;
|
2007-09-24 17:30:42 +00:00
|
|
|
nscoord myPref = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
|
|
|
this, nsLayoutUtils::PREF_WIDTH);
|
|
|
|
aData->currentLine = NSCoordSaturatingAdd(aData->currentLine, myPref);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-06-21 22:32:47 +00:00
|
|
|
nsIFrame::InlineMinWidthData::ForceBreak(nsIRenderingContext *aRenderingContext)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
{
|
|
|
|
currentLine -= trailingWhitespace;
|
2009-09-16 15:01:36 +00:00
|
|
|
prevLines = NS_MAX(prevLines, currentLine);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
currentLine = trailingWhitespace = 0;
|
|
|
|
|
2009-02-03 14:42:18 +00:00
|
|
|
for (PRUint32 i = 0, i_end = floats.Length(); i != i_end; ++i) {
|
|
|
|
nsIFrame *floatFrame = floats[i];
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nscoord float_min =
|
|
|
|
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, floatFrame,
|
|
|
|
nsLayoutUtils::MIN_WIDTH);
|
|
|
|
if (float_min > prevLines)
|
|
|
|
prevLines = float_min;
|
|
|
|
}
|
|
|
|
floats.Clear();
|
|
|
|
trailingTextFrame = nsnull;
|
2007-12-12 00:42:20 +00:00
|
|
|
skipWhitespace = PR_TRUE;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-06-21 22:32:47 +00:00
|
|
|
nsIFrame::InlineMinWidthData::OptionallyBreak(nsIRenderingContext *aRenderingContext)
|
|
|
|
{
|
|
|
|
trailingTextFrame = nsnull;
|
|
|
|
|
|
|
|
// If we can fit more content into a smaller width by staying on this
|
|
|
|
// line (because we're still at a negative offset due to negative
|
|
|
|
// text-indent or negative margin), don't break. Otherwise, do the
|
|
|
|
// same as ForceBreak. it doesn't really matter when we accumulate
|
|
|
|
// floats.
|
|
|
|
if (currentLine < 0 || atStartOfLine)
|
|
|
|
return;
|
|
|
|
ForceBreak(aRenderingContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsIFrame::InlinePrefWidthData::ForceBreak(nsIRenderingContext *aRenderingContext)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
{
|
2009-02-03 14:42:18 +00:00
|
|
|
if (floats.Length() != 0) {
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
// preferred widths accumulated for floats that have already
|
|
|
|
// been cleared past
|
|
|
|
nscoord floats_done = 0,
|
|
|
|
// preferred widths accumulated for floats that have not yet
|
|
|
|
// been cleared past
|
|
|
|
floats_cur_left = 0,
|
|
|
|
floats_cur_right = 0;
|
|
|
|
|
2009-02-03 14:42:18 +00:00
|
|
|
for (PRUint32 i = 0, i_end = floats.Length(); i != i_end; ++i) {
|
|
|
|
nsIFrame *floatFrame = floats[i];
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
const nsStyleDisplay *floatDisp = floatFrame->GetStyleDisplay();
|
|
|
|
if (floatDisp->mBreakType == NS_STYLE_CLEAR_LEFT ||
|
|
|
|
floatDisp->mBreakType == NS_STYLE_CLEAR_RIGHT ||
|
|
|
|
floatDisp->mBreakType == NS_STYLE_CLEAR_LEFT_AND_RIGHT) {
|
2008-03-07 21:20:03 +00:00
|
|
|
nscoord floats_cur = NSCoordSaturatingAdd(floats_cur_left,
|
|
|
|
floats_cur_right);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (floats_cur > floats_done)
|
|
|
|
floats_done = floats_cur;
|
|
|
|
if (floatDisp->mBreakType != NS_STYLE_CLEAR_RIGHT)
|
|
|
|
floats_cur_left = 0;
|
|
|
|
if (floatDisp->mBreakType != NS_STYLE_CLEAR_LEFT)
|
|
|
|
floats_cur_right = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nscoord &floats_cur = floatDisp->mFloats == NS_STYLE_FLOAT_LEFT
|
|
|
|
? floats_cur_left : floats_cur_right;
|
2008-03-25 23:19:46 +00:00
|
|
|
nscoord floatWidth =
|
2008-03-07 21:20:03 +00:00
|
|
|
nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
|
|
|
floatFrame,
|
2008-03-25 23:19:46 +00:00
|
|
|
nsLayoutUtils::PREF_WIDTH);
|
|
|
|
// Negative-width floats don't change the available space so they
|
|
|
|
// shouldn't change our intrinsic line width either.
|
|
|
|
floats_cur =
|
2009-09-16 15:01:36 +00:00
|
|
|
NSCoordSaturatingAdd(floats_cur, NS_MAX(0, floatWidth));
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
}
|
|
|
|
|
2008-03-07 21:20:03 +00:00
|
|
|
nscoord floats_cur =
|
|
|
|
NSCoordSaturatingAdd(floats_cur_left, floats_cur_right);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (floats_cur > floats_done)
|
|
|
|
floats_done = floats_cur;
|
|
|
|
|
2007-11-09 17:16:36 +00:00
|
|
|
currentLine = NSCoordSaturatingAdd(currentLine, floats_done);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
|
|
|
floats.Clear();
|
|
|
|
}
|
|
|
|
|
2008-03-07 21:20:03 +00:00
|
|
|
currentLine =
|
|
|
|
NSCoordSaturatingSubtract(currentLine, trailingWhitespace, nscoord_MAX);
|
2009-09-16 15:01:36 +00:00
|
|
|
prevLines = NS_MAX(prevLines, currentLine);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
currentLine = trailingWhitespace = 0;
|
2007-12-12 00:42:20 +00:00
|
|
|
skipWhitespace = PR_TRUE;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-12-17 14:06:42 +00:00
|
|
|
AddCoord(const nsStyleCoord& aStyle,
|
|
|
|
nsIRenderingContext* aRenderingContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
nscoord* aCoord, float* aPercent)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
{
|
|
|
|
switch (aStyle.GetUnit()) {
|
|
|
|
case eStyleUnit_Coord:
|
|
|
|
*aCoord += aStyle.GetCoordValue();
|
|
|
|
break;
|
|
|
|
case eStyleUnit_Percent:
|
|
|
|
*aPercent += aStyle.GetPercentValue();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsIFrame::IntrinsicWidthOffsetData
|
2006-12-17 14:06:42 +00:00
|
|
|
nsFrame::IntrinsicWidthOffsets(nsIRenderingContext* aRenderingContext)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
{
|
|
|
|
IntrinsicWidthOffsetData result;
|
|
|
|
|
|
|
|
const nsStyleMargin *styleMargin = GetStyleMargin();
|
2008-03-06 00:05:26 +00:00
|
|
|
AddCoord(styleMargin->mMargin.GetLeft(), aRenderingContext, this,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
&result.hMargin, &result.hPctMargin);
|
2008-03-06 00:05:26 +00:00
|
|
|
AddCoord(styleMargin->mMargin.GetRight(), aRenderingContext, this,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
&result.hMargin, &result.hPctMargin);
|
|
|
|
|
|
|
|
const nsStylePadding *stylePadding = GetStylePadding();
|
2008-03-06 00:05:26 +00:00
|
|
|
AddCoord(stylePadding->mPadding.GetLeft(), aRenderingContext, this,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
&result.hPadding, &result.hPctPadding);
|
2008-03-06 00:05:26 +00:00
|
|
|
AddCoord(stylePadding->mPadding.GetRight(), aRenderingContext, this,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
&result.hPadding, &result.hPctPadding);
|
|
|
|
|
|
|
|
const nsStyleBorder *styleBorder = GetStyleBorder();
|
2008-07-17 06:30:25 +00:00
|
|
|
result.hBorder += styleBorder->GetActualBorderWidth(NS_SIDE_LEFT);
|
|
|
|
result.hBorder += styleBorder->GetActualBorderWidth(NS_SIDE_RIGHT);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
2007-01-28 17:20:01 +00:00
|
|
|
const nsStyleDisplay *disp = GetStyleDisplay();
|
|
|
|
if (IsThemed(disp)) {
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext *presContext = PresContext();
|
2007-01-28 17:20:01 +00:00
|
|
|
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntMargin border;
|
2007-01-28 17:20:01 +00:00
|
|
|
presContext->GetTheme()->GetWidgetBorder(presContext->DeviceContext(),
|
|
|
|
this, disp->mAppearance,
|
|
|
|
&border);
|
2007-02-07 07:46:44 +00:00
|
|
|
result.hBorder = presContext->DevPixelsToAppUnits(border.LeftRight());
|
2007-01-28 17:20:01 +00:00
|
|
|
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntMargin padding;
|
2007-01-28 17:20:01 +00:00
|
|
|
if (presContext->GetTheme()->GetWidgetPadding(presContext->DeviceContext(),
|
|
|
|
this, disp->mAppearance,
|
|
|
|
&padding)) {
|
2007-02-07 07:46:44 +00:00
|
|
|
result.hPadding = presContext->DevPixelsToAppUnits(padding.LeftRight());
|
2007-01-28 17:20:01 +00:00
|
|
|
result.hPctPadding = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-11-18 12:09:03 +00:00
|
|
|
/* virtual */ nsIFrame::IntrinsicSize
|
|
|
|
nsFrame::GetIntrinsicSize()
|
|
|
|
{
|
|
|
|
return IntrinsicSize(); // default is width/height set to eStyleUnit_None
|
|
|
|
}
|
|
|
|
|
2007-06-12 18:27:09 +00:00
|
|
|
/* virtual */ nsSize
|
|
|
|
nsFrame::GetIntrinsicRatio()
|
|
|
|
{
|
|
|
|
return nsSize(0, 0);
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
inline PRBool
|
|
|
|
IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
|
|
|
|
{
|
|
|
|
nsStyleUnit unit = aCoord.GetUnit();
|
|
|
|
return unit == eStyleUnit_Auto || // only for 'height'
|
2007-05-11 06:01:31 +00:00
|
|
|
unit == eStyleUnit_None || // only for 'max-height'
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
(unit == eStyleUnit_Percent &&
|
|
|
|
aCBHeight == NS_AUTOHEIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsSize
|
|
|
|
nsFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
|
|
|
|
nsSize aCBSize, nscoord aAvailableWidth,
|
|
|
|
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
|
|
|
PRBool aShrinkWrap)
|
|
|
|
{
|
|
|
|
nsSize result = ComputeAutoSize(aRenderingContext, aCBSize, aAvailableWidth,
|
|
|
|
aMargin, aBorder, aPadding, aShrinkWrap);
|
|
|
|
nsSize boxSizingAdjust(0,0);
|
|
|
|
const nsStylePosition *stylePos = GetStylePosition();
|
|
|
|
|
|
|
|
switch (stylePos->mBoxSizing) {
|
|
|
|
case NS_STYLE_BOX_SIZING_BORDER:
|
|
|
|
boxSizingAdjust += aBorder;
|
|
|
|
// fall through
|
|
|
|
case NS_STYLE_BOX_SIZING_PADDING:
|
|
|
|
boxSizingAdjust += aPadding;
|
|
|
|
}
|
2007-05-03 23:11:00 +00:00
|
|
|
nscoord boxSizingToMarginEdgeWidth =
|
|
|
|
aMargin.width + aBorder.width + aPadding.width - boxSizingAdjust.width;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
|
|
|
// Compute width
|
|
|
|
|
|
|
|
if (stylePos->mWidth.GetUnit() != eStyleUnit_Auto) {
|
2006-12-18 13:20:18 +00:00
|
|
|
result.width =
|
2007-05-03 23:11:00 +00:00
|
|
|
nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
|
|
|
|
aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
|
|
|
|
stylePos->mWidth);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
}
|
|
|
|
|
2007-05-11 06:01:31 +00:00
|
|
|
if (stylePos->mMaxWidth.GetUnit() != eStyleUnit_None) {
|
2006-12-18 13:20:18 +00:00
|
|
|
nscoord maxWidth =
|
2007-05-03 23:11:00 +00:00
|
|
|
nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
|
|
|
|
aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
|
|
|
|
stylePos->mMaxWidth);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (maxWidth < result.width)
|
|
|
|
result.width = maxWidth;
|
|
|
|
}
|
|
|
|
|
2006-12-18 13:20:18 +00:00
|
|
|
nscoord minWidth =
|
2007-05-03 23:11:00 +00:00
|
|
|
nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
|
|
|
|
aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
|
|
|
|
stylePos->mMinWidth);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (minWidth > result.width)
|
|
|
|
result.width = minWidth;
|
|
|
|
|
|
|
|
// Compute height
|
|
|
|
|
|
|
|
if (!IsAutoHeight(stylePos->mHeight, aCBSize.height)) {
|
2006-12-18 13:20:18 +00:00
|
|
|
result.height =
|
2008-07-17 23:37:12 +00:00
|
|
|
nsLayoutUtils::ComputeHeightDependentValue(aCBSize.height,
|
|
|
|
stylePos->mHeight) -
|
2006-12-18 13:20:18 +00:00
|
|
|
boxSizingAdjust.height;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result.height != NS_UNCONSTRAINEDSIZE) {
|
|
|
|
if (!IsAutoHeight(stylePos->mMaxHeight, aCBSize.height)) {
|
2006-12-18 13:20:18 +00:00
|
|
|
nscoord maxHeight =
|
2008-07-17 23:37:12 +00:00
|
|
|
nsLayoutUtils::ComputeHeightDependentValue(aCBSize.height,
|
|
|
|
stylePos->mMaxHeight) -
|
2006-12-18 13:20:18 +00:00
|
|
|
boxSizingAdjust.height;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (maxHeight < result.height)
|
|
|
|
result.height = maxHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsAutoHeight(stylePos->mMinHeight, aCBSize.height)) {
|
2006-12-18 13:20:18 +00:00
|
|
|
nscoord minHeight =
|
2008-07-17 23:37:12 +00:00
|
|
|
nsLayoutUtils::ComputeHeightDependentValue(aCBSize.height,
|
|
|
|
stylePos->mMinHeight) -
|
2006-12-18 13:20:18 +00:00
|
|
|
boxSizingAdjust.height;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (minHeight > result.height)
|
|
|
|
result.height = minHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-17 22:31:07 +00:00
|
|
|
const nsStyleDisplay *disp = GetStyleDisplay();
|
|
|
|
if (IsThemed(disp)) {
|
2009-01-15 03:27:09 +00:00
|
|
|
nsIntSize widget(0, 0);
|
2007-01-17 22:31:07 +00:00
|
|
|
PRBool canOverride = PR_TRUE;
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext *presContext = PresContext();
|
2007-01-17 22:31:07 +00:00
|
|
|
presContext->GetTheme()->
|
|
|
|
GetMinimumWidgetSize(aRenderingContext, this, disp->mAppearance,
|
2009-01-15 03:27:09 +00:00
|
|
|
&widget, &canOverride);
|
2007-01-17 22:31:07 +00:00
|
|
|
|
2009-01-15 03:27:09 +00:00
|
|
|
nsSize size;
|
|
|
|
size.width = presContext->DevPixelsToAppUnits(widget.width);
|
|
|
|
size.height = presContext->DevPixelsToAppUnits(widget.height);
|
2007-01-17 22:31:07 +00:00
|
|
|
|
|
|
|
// GMWS() returns border-box; we need content-box
|
|
|
|
size.width -= aBorder.width + aPadding.width;
|
|
|
|
size.height -= aBorder.height + aPadding.height;
|
|
|
|
|
|
|
|
if (size.height > result.height || !canOverride)
|
|
|
|
result.height = size.height;
|
|
|
|
if (size.width > result.width || !canOverride)
|
|
|
|
result.width = size.width;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.width < 0)
|
|
|
|
result.width = 0;
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (result.height < 0)
|
|
|
|
result.height = 0;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-10-12 08:30:54 +00:00
|
|
|
nsRect
|
|
|
|
nsIFrame::ComputeTightBounds(gfxContext* aContext) const
|
|
|
|
{
|
|
|
|
return GetOverflowRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect
|
|
|
|
nsFrame::ComputeSimpleTightBounds(gfxContext* aContext) const
|
|
|
|
{
|
|
|
|
if (GetStyleOutline()->GetOutlineStyle() != NS_STYLE_BORDER_STYLE_NONE ||
|
|
|
|
HasBorder() || !GetStyleBackground()->IsTransparent() ||
|
|
|
|
GetStyleDisplay()->mAppearance) {
|
|
|
|
// Not necessarily tight, due to clipping, negative
|
|
|
|
// outline-offset, and lots of other issues, but that's OK
|
|
|
|
return GetOverflowRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect r(0, 0, 0, 0);
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
nsIAtom* childList = nsnull;
|
|
|
|
do {
|
|
|
|
nsIFrame* child = GetFirstChild(childList);
|
|
|
|
while (child) {
|
|
|
|
r.UnionRect(r, child->ComputeTightBounds(aContext) + child->GetPosition());
|
|
|
|
child = child->GetNextSibling();
|
|
|
|
}
|
|
|
|
childList = GetAdditionalChildListName(listIndex++);
|
|
|
|
} while (childList);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
/* virtual */ nsSize
|
|
|
|
nsFrame::ComputeAutoSize(nsIRenderingContext *aRenderingContext,
|
|
|
|
nsSize aCBSize, nscoord aAvailableWidth,
|
|
|
|
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
|
|
|
PRBool aShrinkWrap)
|
|
|
|
{
|
|
|
|
// Use basic shrink-wrapping as a default implementation.
|
|
|
|
nsSize result(0xdeadbeef, NS_UNCONSTRAINEDSIZE);
|
|
|
|
|
|
|
|
// don't bother setting it if the result won't be used
|
|
|
|
if (GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto) {
|
|
|
|
nscoord availBased = aAvailableWidth - aMargin.width - aBorder.width -
|
|
|
|
aPadding.width;
|
|
|
|
result.width = ShrinkWidthToFit(aRenderingContext, availBased);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
nscoord
|
|
|
|
nsFrame::ShrinkWidthToFit(nsIRenderingContext *aRenderingContext,
|
|
|
|
nscoord aWidthInCB)
|
|
|
|
{
|
|
|
|
nscoord result;
|
|
|
|
nscoord minWidth = GetMinWidth(aRenderingContext);
|
|
|
|
if (minWidth > aWidthInCB) {
|
|
|
|
result = minWidth;
|
|
|
|
} else {
|
|
|
|
nscoord prefWidth = GetPrefWidth(aRenderingContext);
|
|
|
|
if (prefWidth > aWidthInCB) {
|
|
|
|
result = aWidthInCB;
|
|
|
|
} else {
|
|
|
|
result = prefWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
1998-05-14 00:47:32 +00:00
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::WillReflow(nsPresContext* aPresContext)
|
1998-05-14 00:47:32 +00:00
|
|
|
{
|
2003-01-16 19:21:23 +00:00
|
|
|
#ifdef DEBUG_dbaron_off
|
2002-12-11 02:29:35 +00:00
|
|
|
// bug 81268
|
|
|
|
NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW),
|
|
|
|
"nsFrame::WillReflow: frame is already in reflow");
|
2002-12-11 03:35:21 +00:00
|
|
|
#endif
|
2002-12-11 02:29:35 +00:00
|
|
|
|
1998-06-25 16:33:10 +00:00
|
|
|
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
|
|
|
("WillReflow: oldState=%x", mState));
|
1998-05-14 00:47:32 +00:00
|
|
|
mState |= NS_FRAME_IN_REFLOW;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::DidReflow(nsPresContext* aPresContext,
|
2001-12-07 14:51:12 +00:00
|
|
|
const nsHTMLReflowState* aReflowState,
|
|
|
|
nsDidReflowStatus aStatus)
|
1998-05-14 00:47:32 +00:00
|
|
|
{
|
1998-06-25 16:33:10 +00:00
|
|
|
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
|
|
|
("nsFrame::DidReflow: aStatus=%d", aStatus));
|
1998-05-14 00:47:32 +00:00
|
|
|
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
|
2000-01-12 08:28:24 +00:00
|
|
|
mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
1999-12-01 04:13:19 +00:00
|
|
|
}
|
1998-05-28 21:55:13 +00:00
|
|
|
|
2007-11-06 22:47:29 +00:00
|
|
|
// Notify the percent height observer if there is a percent height.
|
|
|
|
// The observer may be able to initiate another reflow with a computed
|
|
|
|
// height. This happens in the case where a table cell has no computed
|
|
|
|
// height but can fabricate one when the cell height is known.
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (aReflowState && aReflowState->mPercentHeightObserver &&
|
2001-12-07 14:51:12 +00:00
|
|
|
(eStyleUnit_Percent == aReflowState->mStylePosition->mHeight.GetUnit())) {
|
|
|
|
|
2004-09-14 02:28:03 +00:00
|
|
|
nsIFrame* prevInFlow = GetPrevInFlow();
|
2002-04-10 21:32:41 +00:00
|
|
|
if (!prevInFlow) { // 1st in flow
|
|
|
|
aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
|
|
|
|
}
|
2001-12-07 14:51:12 +00:00
|
|
|
}
|
|
|
|
|
1998-05-14 00:47:32 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
/* virtual */ PRBool
|
|
|
|
nsFrame::CanContinueTextRun() const
|
2000-07-28 22:29:28 +00:00
|
|
|
{
|
|
|
|
// By default, a frame will *not* allow a text run to be continued
|
|
|
|
// through it.
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
return PR_FALSE;
|
2000-07-28 22:29:28 +00:00
|
|
|
}
|
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::Reflow(nsPresContext* aPresContext,
|
1998-10-09 23:46:02 +00:00
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
DO_GLOBAL_REFLOW_COUNT("nsFrame");
|
1998-04-13 20:24:54 +00:00
|
|
|
aDesiredSize.width = 0;
|
|
|
|
aDesiredSize.height = 0;
|
1998-05-12 04:17:56 +00:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
2002-05-28 22:50:43 +00:00
|
|
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
1998-10-01 04:46:11 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-27 16:51:21 +00:00
|
|
|
NS_IMETHODIMP
|
2009-08-05 01:38:10 +00:00
|
|
|
nsFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
|
1998-10-27 16:51:21 +00:00
|
|
|
{
|
2004-02-20 21:38:31 +00:00
|
|
|
NS_NOTREACHED("should only be called for text frames");
|
|
|
|
return NS_OK;
|
1998-10-27 16:51:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2005-09-07 16:49:21 +00:00
|
|
|
nsFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
1998-10-27 16:51:21 +00:00
|
|
|
nsIAtom* aAttribute,
|
2003-07-11 21:16:12 +00:00
|
|
|
PRInt32 aModType)
|
1998-09-18 19:53:27 +00:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Flow member functions
|
|
|
|
|
2006-12-20 03:52:34 +00:00
|
|
|
nsSplittableType
|
|
|
|
nsFrame::GetSplittableType() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2006-12-20 03:52:34 +00:00
|
|
|
return NS_FRAME_NOT_SPLITTABLE;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2006-02-21 21:33:47 +00:00
|
|
|
nsIFrame* nsFrame::GetPrevContinuation() const
|
|
|
|
{
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsFrame::SetPrevContinuation(nsIFrame* aPrevContinuation)
|
|
|
|
{
|
|
|
|
// Ignore harmless requests to set it to NULL
|
|
|
|
if (aPrevContinuation) {
|
|
|
|
NS_ERROR("not splittable");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame* nsFrame::GetNextContinuation() const
|
|
|
|
{
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsFrame::SetNextContinuation(nsIFrame*)
|
|
|
|
{
|
|
|
|
NS_ERROR("not splittable");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame* nsFrame::GetPrevInFlowVirtual() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2004-09-14 02:28:03 +00:00
|
|
|
return nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1999-10-27 00:53:15 +00:00
|
|
|
NS_IMETHODIMP nsFrame::SetPrevInFlow(nsIFrame* aPrevInFlow)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-10-27 00:53:15 +00:00
|
|
|
// Ignore harmless requests to set it to NULL
|
|
|
|
if (aPrevInFlow) {
|
|
|
|
NS_ERROR("not splittable");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2006-02-21 21:33:47 +00:00
|
|
|
nsIFrame* nsFrame::GetNextInFlowVirtual() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2004-09-14 02:28:03 +00:00
|
|
|
return nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP nsFrame::SetNextInFlow(nsIFrame*)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_ERROR("not splittable");
|
1998-05-08 17:02:35 +00:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2008-01-27 08:13:19 +00:00
|
|
|
nsIFrame* nsIFrame::GetTailContinuation()
|
|
|
|
{
|
|
|
|
nsIFrame* frame = this;
|
|
|
|
while (frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
|
|
|
|
frame = frame->GetPrevContinuation();
|
|
|
|
NS_ASSERTION(frame, "first continuation can't be overflow container");
|
|
|
|
}
|
|
|
|
for (nsIFrame* next = frame->GetNextContinuation();
|
|
|
|
next && !(next->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER);
|
|
|
|
next = frame->GetNextContinuation()) {
|
|
|
|
frame = next;
|
|
|
|
}
|
|
|
|
NS_POSTCONDITION(frame, "illegal state in continuation chain.");
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
2005-04-07 23:54:28 +00:00
|
|
|
nsIView*
|
|
|
|
nsIFrame::GetParentViewForChildFrame(nsIFrame* aFrame) const
|
|
|
|
{
|
|
|
|
return GetClosestView();
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Associated view object
|
2003-06-19 23:44:01 +00:00
|
|
|
nsIView*
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::GetView() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2003-06-19 23:44:01 +00:00
|
|
|
// Check the frame state bit and see if the frame has a view
|
2003-07-12 00:50:00 +00:00
|
|
|
if (!(GetStateBits() & NS_FRAME_HAS_VIEW))
|
2003-06-19 23:44:01 +00:00
|
|
|
return nsnull;
|
1999-10-27 03:56:14 +00:00
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
// Check for a property on the frame
|
2004-02-23 21:29:06 +00:00
|
|
|
nsresult rv;
|
2006-12-26 17:47:52 +00:00
|
|
|
void *value = GetProperty(nsGkAtoms::viewProperty, &rv);
|
2004-02-23 21:29:06 +00:00
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
|
|
NS_ASSERTION(value, "frame state bit was set but frame has no view");
|
2007-07-08 07:08:04 +00:00
|
|
|
return static_cast<nsIView*>(value);
|
2003-06-19 23:44:01 +00:00
|
|
|
}
|
1999-10-27 03:56:14 +00:00
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
/* virtual */ nsIView*
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::GetViewExternal() const
|
2003-06-19 23:44:01 +00:00
|
|
|
{
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return GetView();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
nsresult
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::SetView(nsIView* aView)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-10-27 03:56:14 +00:00
|
|
|
if (aView) {
|
1998-08-28 02:52:54 +00:00
|
|
|
aView->SetClientData(this);
|
1999-10-27 03:56:14 +00:00
|
|
|
|
|
|
|
// Set a property on the frame
|
2006-12-26 17:47:52 +00:00
|
|
|
nsresult rv = SetProperty(nsGkAtoms::viewProperty, aView, nsnull);
|
2003-06-19 23:44:01 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2000-02-03 00:51:37 +00:00
|
|
|
|
|
|
|
// Set the frame state bit that says the frame has a view
|
2003-07-12 00:50:00 +00:00
|
|
|
AddStateBits(NS_FRAME_HAS_VIEW);
|
2001-08-01 04:37:17 +00:00
|
|
|
|
2003-07-12 00:50:00 +00:00
|
|
|
// Let all of the ancestors know they have a descendant with a view.
|
|
|
|
for (nsIFrame* f = GetParent();
|
|
|
|
f && !(f->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW);
|
|
|
|
f = f->GetParent())
|
|
|
|
f->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 02:52:54 +00:00
|
|
|
|
1999-10-27 03:56:14 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2003-06-21 18:57:14 +00:00
|
|
|
nsIFrame* nsIFrame::GetAncestorWithViewExternal() const
|
|
|
|
{
|
|
|
|
return GetAncestorWithView();
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Find the first geometric parent that has a view
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame* nsIFrame::GetAncestorWithView() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
for (nsIFrame* f = mParent; nsnull != f; f = f->GetParent()) {
|
|
|
|
if (f->HasView()) {
|
|
|
|
return f;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2004-11-03 16:16:57 +00:00
|
|
|
// virtual
|
|
|
|
nsPoint nsIFrame::GetOffsetToExternal(const nsIFrame* aOther) const
|
|
|
|
{
|
|
|
|
return GetOffsetTo(aOther);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPoint nsIFrame::GetOffsetTo(const nsIFrame* aOther) const
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aOther,
|
|
|
|
"Must have frame for destination coordinate system!");
|
|
|
|
nsPoint offset(0, 0);
|
|
|
|
const nsIFrame* f;
|
2008-09-06 08:52:56 +00:00
|
|
|
for (f = this; f != aOther && f;
|
|
|
|
f = nsLayoutUtils::GetCrossDocParentFrame(f, &offset)) {
|
2004-11-03 16:16:57 +00:00
|
|
|
offset += f->GetPosition();
|
|
|
|
}
|
2008-09-06 08:52:56 +00:00
|
|
|
|
2004-11-03 16:16:57 +00:00
|
|
|
if (f != aOther) {
|
2008-09-06 08:52:56 +00:00
|
|
|
// Looks like aOther wasn't an ancestor of |this|. So now we have
|
|
|
|
// the root-document-relative position of |this| in |offset|. Convert back
|
|
|
|
// to the coordinates of aOther
|
|
|
|
nsPoint negativeOffset(0,0);
|
|
|
|
while (aOther) {
|
|
|
|
offset -= aOther->GetPosition();
|
|
|
|
aOther = nsLayoutUtils::GetCrossDocParentFrame(aOther, &negativeOffset);
|
|
|
|
}
|
|
|
|
offset -= negativeOffset;
|
2004-11-03 16:16:57 +00:00
|
|
|
}
|
2008-09-06 08:52:56 +00:00
|
|
|
|
2004-11-03 16:16:57 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2004-11-23 17:26:19 +00:00
|
|
|
// virtual
|
|
|
|
nsIntRect nsIFrame::GetScreenRectExternal() const
|
|
|
|
{
|
|
|
|
return GetScreenRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntRect nsIFrame::GetScreenRect() const
|
|
|
|
{
|
2009-05-08 02:31:04 +00:00
|
|
|
return GetScreenRectInAppUnits().ToNearestPixels(PresContext()->AppUnitsPerDevPixel());
|
2008-06-16 01:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// virtual
|
|
|
|
nsRect nsIFrame::GetScreenRectInAppUnitsExternal() const
|
|
|
|
{
|
|
|
|
return GetScreenRectInAppUnits();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect nsIFrame::GetScreenRectInAppUnits() const
|
|
|
|
{
|
2009-07-22 00:45:06 +00:00
|
|
|
nsPresContext* presContext = PresContext();
|
|
|
|
nsIFrame* rootFrame =
|
|
|
|
presContext->PresShell()->FrameManager()->GetRootFrame();
|
|
|
|
nsPoint rootScreenPos(0, 0);
|
|
|
|
nsPoint rootFrameOffsetInParent(0, 0);
|
|
|
|
nsIFrame* rootFrameParent =
|
|
|
|
nsLayoutUtils::GetCrossDocParentFrame(rootFrame, &rootFrameOffsetInParent);
|
|
|
|
if (rootFrameParent) {
|
|
|
|
nsRect parentScreenRectAppUnits = rootFrameParent->GetScreenRectInAppUnits();
|
|
|
|
nsPresContext* parentPresContext = rootFrameParent->PresContext();
|
|
|
|
double parentScale = double(presContext->AppUnitsPerDevPixel())/
|
|
|
|
parentPresContext->AppUnitsPerDevPixel();
|
|
|
|
nsPoint rootPt = parentScreenRectAppUnits.TopLeft() + rootFrameOffsetInParent;
|
|
|
|
rootScreenPos.x = NS_round(parentScale*rootPt.x);
|
|
|
|
rootScreenPos.y = NS_round(parentScale*rootPt.y);
|
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIWidget> rootWidget;
|
|
|
|
presContext->PresShell()->GetViewManager()->GetRootWidget(getter_AddRefs(rootWidget));
|
|
|
|
if (rootWidget) {
|
|
|
|
nsIntPoint rootDevPx = rootWidget->WidgetToScreenOffset();
|
|
|
|
rootScreenPos.x = presContext->DevPixelsToAppUnits(rootDevPx.x);
|
|
|
|
rootScreenPos.y = presContext->DevPixelsToAppUnits(rootDevPx.y);
|
2004-11-23 17:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-22 00:45:06 +00:00
|
|
|
return nsRect(rootScreenPos + GetOffsetTo(rootFrame), GetSize());
|
2004-11-23 17:26:19 +00:00
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Returns the offset from this frame to the closest geometric parent that
|
|
|
|
// has a view. Also returns the containing view or null in case of error
|
2004-12-26 19:48:54 +00:00
|
|
|
NS_IMETHODIMP nsFrame::GetOffsetFromView(nsPoint& aOffset,
|
|
|
|
nsIView** aView) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-02-10 05:38:18 +00:00
|
|
|
NS_PRECONDITION(nsnull != aView, "null OUT parameter pointer");
|
1998-04-17 01:41:24 +00:00
|
|
|
nsIFrame* frame = (nsIFrame*)this;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1999-02-10 05:38:18 +00:00
|
|
|
*aView = nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
aOffset.MoveTo(0, 0);
|
|
|
|
do {
|
2003-06-28 11:48:14 +00:00
|
|
|
aOffset += frame->GetPosition();
|
|
|
|
frame = frame->GetParent();
|
2003-06-19 23:44:01 +00:00
|
|
|
} while (frame && !frame->HasView());
|
|
|
|
if (frame)
|
2003-06-28 11:48:14 +00:00
|
|
|
*aView = frame->GetView();
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
/* virtual */ PRBool
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::AreAncestorViewsVisible() const
|
2003-06-19 23:44:01 +00:00
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
for (nsIView* view = GetClosestView(); view; view = view->GetParent()) {
|
|
|
|
if (view->GetVisibility() == nsViewVisibility_kHide) {
|
2003-06-19 23:44:01 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2002-02-07 22:39:15 +00:00
|
|
|
|
2005-02-07 21:59:35 +00:00
|
|
|
nsIWidget*
|
|
|
|
nsIFrame::GetWindow() const
|
|
|
|
{
|
|
|
|
return GetClosestView()->GetNearestWidget(nsnull);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2003-10-31 20:19:18 +00:00
|
|
|
nsIAtom*
|
|
|
|
nsFrame::GetType() const
|
1999-02-09 05:44:13 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
return nsnull;
|
1999-02-09 05:44:13 +00:00
|
|
|
}
|
|
|
|
|
2005-08-16 22:52:48 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::IsLeaf() const
|
|
|
|
{
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2001-08-18 07:25:52 +00:00
|
|
|
void
|
2008-09-18 09:47:21 +00:00
|
|
|
nsIFrame::InvalidateWithFlags(const nsRect& aDamageRect, PRUint32 aFlags)
|
1998-06-02 05:28:11 +00:00
|
|
|
{
|
2001-11-06 01:44:20 +00:00
|
|
|
if (aDamageRect.IsEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-02-22 03:31:30 +00:00
|
|
|
// Don't allow invalidates to do anything when
|
|
|
|
// painting is suppressed.
|
2007-03-30 21:11:41 +00:00
|
|
|
nsIPresShell *shell = PresContext()->GetPresShell();
|
2004-02-22 03:31:30 +00:00
|
|
|
if (shell) {
|
|
|
|
PRBool suppressed = PR_FALSE;
|
|
|
|
shell->IsPaintingSuppressed(&suppressed);
|
|
|
|
if (suppressed)
|
|
|
|
return;
|
2001-04-25 19:52:49 +00:00
|
|
|
}
|
2006-06-08 01:11:43 +00:00
|
|
|
|
2008-09-18 09:47:21 +00:00
|
|
|
InvalidateInternal(aDamageRect, 0, 0, nsnull, aFlags);
|
2006-06-08 01:11:43 +00:00
|
|
|
}
|
2001-04-25 19:52:49 +00:00
|
|
|
|
2008-09-13 09:42:11 +00:00
|
|
|
/**
|
|
|
|
* Helper function that funnels an InvalidateInternal request up to the
|
|
|
|
* parent. This function is used so that if MOZ_SVG is not defined, we still
|
|
|
|
* have unified control paths in the InvalidateInternal chain.
|
|
|
|
*
|
|
|
|
* @param aDamageRect The rect to invalidate.
|
|
|
|
* @param aX The x offset from the origin of this frame to the rectangle.
|
|
|
|
* @param aY The y offset from the origin of this frame to the rectangle.
|
|
|
|
* @param aImmediate Whether to redraw immediately.
|
|
|
|
* @return None, though this funnels the request up to the parent frame.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
nsIFrame::InvalidateInternalAfterResize(const nsRect& aDamageRect, nscoord aX,
|
2008-09-18 09:47:21 +00:00
|
|
|
nscoord aY, PRUint32 aFlags)
|
2008-09-13 09:42:11 +00:00
|
|
|
{
|
|
|
|
/* If we're a transformed frame, then we need to apply our transform to the
|
|
|
|
* damage rectangle so that the redraw correctly redraws the transformed
|
|
|
|
* region. We're moved over aX and aY from our origin, but since this aX
|
|
|
|
* and aY is contained within our border, we need to scoot back by -aX and
|
|
|
|
* -aY to get back to the origin of the transform.
|
|
|
|
*
|
|
|
|
* There's one more problem, though, and that's that we don't know what
|
|
|
|
* coordinate space this rectangle is in. Sometimes it's in the local
|
|
|
|
* coordinate space for the frame, and sometimes its in the transformed
|
|
|
|
* coordinate space. If we get it wrong, we'll display incorrectly. Until I
|
|
|
|
* find a better fix for this problem, we'll invalidate the union of the two
|
|
|
|
* rectangles (original rectangle and transformed rectangle). At least one of
|
|
|
|
* these will be correct.
|
|
|
|
*
|
|
|
|
* See bug #452496 for more details.
|
|
|
|
*/
|
2008-10-01 00:51:05 +00:00
|
|
|
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
2008-09-13 09:42:11 +00:00
|
|
|
GetStyleDisplay()->HasTransform()) {
|
|
|
|
nsRect newDamageRect;
|
|
|
|
newDamageRect.UnionRect(nsDisplayTransform::TransformRect
|
|
|
|
(aDamageRect, this, nsPoint(-aX, -aY)), aDamageRect);
|
|
|
|
GetParent()->
|
|
|
|
InvalidateInternal(newDamageRect, aX + mRect.x, aY + mRect.y, this,
|
2008-09-18 09:47:21 +00:00
|
|
|
aFlags);
|
2008-09-13 09:42:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
GetParent()->
|
2008-09-18 09:47:21 +00:00
|
|
|
InvalidateInternal(aDamageRect, aX + mRect.x, aY + mRect.y, this, aFlags);
|
2008-09-13 09:42:11 +00:00
|
|
|
}
|
|
|
|
|
2006-06-08 01:11:43 +00:00
|
|
|
void
|
|
|
|
nsIFrame::InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
|
2008-09-18 09:47:21 +00:00
|
|
|
nsIFrame* aForChild, PRUint32 aFlags)
|
2006-06-08 01:11:43 +00:00
|
|
|
{
|
2008-09-11 00:24:16 +00:00
|
|
|
#ifdef MOZ_SVG
|
|
|
|
if (nsSVGIntegrationUtils::UsingEffectsForFrame(this)) {
|
|
|
|
nsRect r = nsSVGIntegrationUtils::GetInvalidAreaForChangedSource(this,
|
|
|
|
aDamageRect + nsPoint(aX, aY));
|
2008-09-13 09:42:11 +00:00
|
|
|
/* Rectangle is now in our own local space, so aX and aY are effectively
|
|
|
|
* zero. Thus we'll pretend that the entire time this was in our own
|
|
|
|
* local coordinate space and do any remaining processing.
|
|
|
|
*/
|
2008-09-18 09:47:21 +00:00
|
|
|
InvalidateInternalAfterResize(r, 0, 0, aFlags);
|
2008-09-11 00:24:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2008-09-13 09:42:11 +00:00
|
|
|
|
2008-09-18 09:47:21 +00:00
|
|
|
InvalidateInternalAfterResize(aDamageRect, aX, aY, aFlags);
|
2008-09-13 09:42:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxMatrix
|
|
|
|
nsIFrame::GetTransformMatrix(nsIFrame **aOutAncestor)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aOutAncestor, "Need a place to put the ancestor!");
|
|
|
|
|
|
|
|
/* Whether or not we're transformed, the matrix will be relative to our
|
|
|
|
* cross-doc parent frame.
|
|
|
|
*/
|
|
|
|
*aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(this);
|
|
|
|
|
|
|
|
/* If we're transformed, we want to hand back the combination
|
|
|
|
* transform/translate matrix that will apply our current transform, then
|
|
|
|
* shift us to our parent.
|
|
|
|
*/
|
|
|
|
if (IsTransformed()) {
|
|
|
|
/* Compute the delta to the parent, which we need because we are converting
|
|
|
|
* coordinates to our parent.
|
|
|
|
*/
|
|
|
|
NS_ASSERTION(*aOutAncestor, "Cannot transform the viewport frame!");
|
|
|
|
nsPoint delta = GetOffsetTo(*aOutAncestor);
|
|
|
|
PRInt32 scaleFactor = PresContext()->AppUnitsPerDevPixel();
|
|
|
|
|
|
|
|
gfxMatrix result =
|
|
|
|
nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0),
|
|
|
|
scaleFactor);
|
|
|
|
/* Combine the raw transform with a translation to our parent. */
|
|
|
|
result *= gfxMatrix().Translate
|
|
|
|
(gfxPoint(NSAppUnitsToFloatPixels(delta.x, scaleFactor),
|
|
|
|
NSAppUnitsToFloatPixels(delta.y, scaleFactor)));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise, we're not transformed. In that case, we'll walk up the frame
|
|
|
|
* tree until we either hit the root frame or something that may be
|
|
|
|
* transformed. We'll then change coordinates into that frame, since we're
|
|
|
|
* guaranteed that nothing in-between can be transformed. First, however,
|
|
|
|
* we have to check to see if we have a parent. If not, we'll set the
|
|
|
|
* outparam to null (indicating that there's nothing left) and will hand back
|
|
|
|
* the identity matrix.
|
|
|
|
*/
|
|
|
|
if (!*aOutAncestor)
|
|
|
|
return gfxMatrix();
|
|
|
|
|
|
|
|
/* Keep iterating while the frame can't possibly be transformed. */
|
2008-10-01 00:51:05 +00:00
|
|
|
while (!(*aOutAncestor)->IsTransformed()) {
|
2008-09-13 09:42:11 +00:00
|
|
|
/* If no parent, stop iterating. Otherwise, update the ancestor. */
|
|
|
|
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(*aOutAncestor);
|
|
|
|
if (!parent)
|
|
|
|
break;
|
2008-09-11 00:24:16 +00:00
|
|
|
|
2008-09-13 09:42:11 +00:00
|
|
|
*aOutAncestor = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(*aOutAncestor, "Somehow ended up with a null ancestor...?");
|
|
|
|
|
|
|
|
/* Translate from this frame to our ancestor, if it exists. That's the
|
|
|
|
* entire transform, so we're done.
|
|
|
|
*/
|
|
|
|
nsPoint delta = GetOffsetTo(*aOutAncestor);
|
|
|
|
PRInt32 scaleFactor = PresContext()->AppUnitsPerDevPixel();
|
|
|
|
return gfxMatrix().Translate
|
|
|
|
(gfxPoint(NSAppUnitsToFloatPixels(delta.x, scaleFactor),
|
|
|
|
NSAppUnitsToFloatPixels(delta.y, scaleFactor)));
|
2006-06-08 01:11:43 +00:00
|
|
|
}
|
1999-08-19 14:36:47 +00:00
|
|
|
|
2008-02-08 09:36:32 +00:00
|
|
|
void
|
|
|
|
nsIFrame::InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2)
|
|
|
|
{
|
|
|
|
nsRect sizeHStrip, sizeVStrip;
|
|
|
|
nsLayoutUtils::GetRectDifferenceStrips(aR1, aR2, &sizeHStrip, &sizeVStrip);
|
|
|
|
Invalidate(sizeVStrip);
|
|
|
|
Invalidate(sizeHStrip);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsIFrame::InvalidateOverflowRect()
|
|
|
|
{
|
|
|
|
Invalidate(GetOverflowRect());
|
|
|
|
}
|
|
|
|
|
2006-06-08 01:11:43 +00:00
|
|
|
void
|
2008-09-18 09:47:21 +00:00
|
|
|
nsIFrame::InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags)
|
2006-06-08 01:11:43 +00:00
|
|
|
{
|
2008-09-18 09:47:21 +00:00
|
|
|
if (aFlags & INVALIDATE_NOTIFY_ONLY)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PRUint32 flags =
|
|
|
|
(aFlags & INVALIDATE_IMMEDIATE) ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
|
2006-06-08 01:11:43 +00:00
|
|
|
nsIView* view = GetView();
|
|
|
|
NS_ASSERTION(view, "This can only be called on frames with views");
|
2008-09-18 09:47:21 +00:00
|
|
|
view->GetViewManager()->UpdateView(view, aDamageRect, flags);
|
1998-06-02 05:28:11 +00:00
|
|
|
}
|
1998-05-13 22:38:09 +00:00
|
|
|
|
2008-09-11 00:24:16 +00:00
|
|
|
static void
|
|
|
|
DestroyRectFunc(void* aFrame,
|
|
|
|
nsIAtom* aPropertyName,
|
|
|
|
void* aPropertyValue,
|
|
|
|
void* aDtorData)
|
|
|
|
{
|
|
|
|
delete static_cast<nsRect*>(aPropertyValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SetRectProperty(nsIFrame* aFrame, nsIAtom* aProp, const nsRect& aRect)
|
|
|
|
{
|
|
|
|
nsRect* r = new nsRect(aRect);
|
|
|
|
if (!r)
|
|
|
|
return;
|
|
|
|
aFrame->SetProperty(aProp, r, DestroyRectFunc);
|
|
|
|
}
|
|
|
|
|
2008-10-21 07:42:28 +00:00
|
|
|
/**
|
|
|
|
* @param aAnyOutlineOrEffects set to true if this frame has any
|
|
|
|
* outline, SVG effects or box shadows that mean we need to invalidate
|
|
|
|
* the whole overflow area if the frame's size changes.
|
|
|
|
*/
|
2008-09-11 00:24:16 +00:00
|
|
|
static nsRect
|
|
|
|
ComputeOutlineAndEffectsRect(nsIFrame* aFrame, PRBool* aAnyOutlineOrEffects,
|
|
|
|
const nsRect& aOverflowRect,
|
|
|
|
PRBool aStoreRectProperties) {
|
|
|
|
nsRect r = aOverflowRect;
|
|
|
|
*aAnyOutlineOrEffects = PR_FALSE;
|
|
|
|
|
|
|
|
// box-shadow
|
2009-04-05 23:35:53 +00:00
|
|
|
nsCSSShadowArray* boxShadows = aFrame->GetEffectiveBoxShadows();
|
|
|
|
if (boxShadows) {
|
2008-09-11 00:24:16 +00:00
|
|
|
nsRect shadows;
|
|
|
|
for (PRUint32 i = 0; i < boxShadows->Length(); ++i) {
|
|
|
|
nsRect tmpRect = r;
|
|
|
|
nsCSSShadowItem* shadow = boxShadows->ShadowAt(i);
|
2009-02-10 08:45:13 +00:00
|
|
|
|
|
|
|
// inset shadows are never painted outside the frame
|
|
|
|
if (shadow->mInset)
|
|
|
|
continue;
|
2008-09-13 03:45:37 +00:00
|
|
|
nscoord outsetRadius = shadow->mRadius + shadow->mSpread;
|
2008-09-11 00:24:16 +00:00
|
|
|
|
2008-09-13 03:45:37 +00:00
|
|
|
tmpRect.MoveBy(nsPoint(shadow->mXOffset, shadow->mYOffset));
|
2008-09-11 00:24:16 +00:00
|
|
|
tmpRect.Inflate(outsetRadius, outsetRadius);
|
|
|
|
|
|
|
|
shadows.UnionRect(shadows, tmpRect);
|
|
|
|
}
|
|
|
|
r.UnionRect(r, shadows);
|
2008-10-21 07:42:28 +00:00
|
|
|
*aAnyOutlineOrEffects = PR_TRUE;
|
2008-09-11 00:24:16 +00:00
|
|
|
}
|
|
|
|
|
2004-08-26 00:07:56 +00:00
|
|
|
const nsStyleOutline* outline = aFrame->GetStyleOutline();
|
2004-03-10 03:09:05 +00:00
|
|
|
PRUint8 outlineStyle = outline->GetOutlineStyle();
|
|
|
|
if (outlineStyle != NS_STYLE_BORDER_STYLE_NONE) {
|
|
|
|
nscoord width;
|
|
|
|
#ifdef DEBUG
|
|
|
|
PRBool result =
|
|
|
|
#endif
|
|
|
|
outline->GetOutlineWidth(width);
|
|
|
|
NS_ASSERTION(result, "GetOutlineWidth had no cached outline width");
|
|
|
|
if (width > 0) {
|
2008-09-11 00:24:16 +00:00
|
|
|
if (aStoreRectProperties) {
|
|
|
|
SetRectProperty(aFrame, nsGkAtoms::outlineInnerRectProperty, r);
|
|
|
|
}
|
|
|
|
|
2008-09-13 03:45:37 +00:00
|
|
|
nscoord offset = outline->mOutlineOffset;
|
2009-09-16 15:01:36 +00:00
|
|
|
nscoord inflateBy = NS_MAX(width + offset, 0);
|
2004-10-26 12:57:15 +00:00
|
|
|
r.Inflate(inflateBy, inflateBy);
|
2008-09-11 00:24:16 +00:00
|
|
|
*aAnyOutlineOrEffects = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note that we don't remove the outlineInnerRect if a frame loses outline
|
|
|
|
// style. That would require an extra property lookup for every frame,
|
|
|
|
// or a new frame state bit to track whether a property had been stored,
|
|
|
|
// or something like that. It's not worth doing that here. At most it's
|
|
|
|
// only one heap-allocated rect per frame and it will be cleaned up when
|
|
|
|
// the frame dies.
|
|
|
|
|
|
|
|
#ifdef MOZ_SVG
|
|
|
|
if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
|
|
|
|
*aAnyOutlineOrEffects = PR_TRUE;
|
|
|
|
if (aStoreRectProperties) {
|
|
|
|
SetRectProperty(aFrame, nsGkAtoms::preEffectsBBoxProperty, r);
|
2004-03-10 03:09:05 +00:00
|
|
|
}
|
2008-09-11 00:24:16 +00:00
|
|
|
r = nsSVGIntegrationUtils::ComputeFrameEffectsRect(aFrame, r);
|
2004-03-10 03:09:05 +00:00
|
|
|
}
|
2008-09-11 00:24:16 +00:00
|
|
|
#endif
|
|
|
|
|
2004-03-10 03:09:05 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-04-18 07:40:35 +00:00
|
|
|
nsPoint
|
|
|
|
nsIFrame::GetRelativeOffset(const nsStyleDisplay* aDisplay) const
|
|
|
|
{
|
|
|
|
if (!aDisplay || NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition) {
|
|
|
|
nsPoint *offsets = static_cast<nsPoint*>
|
|
|
|
(GetProperty(nsGkAtoms::computedOffsetProperty));
|
|
|
|
if (offsets) {
|
|
|
|
return *offsets;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nsPoint(0,0);
|
|
|
|
}
|
|
|
|
|
2004-08-26 00:07:56 +00:00
|
|
|
nsRect
|
|
|
|
nsIFrame::GetOverflowRect() const
|
|
|
|
{
|
|
|
|
// Note that in some cases the overflow area might not have been
|
|
|
|
// updated (yet) to reflect any outline set on the frame or the area
|
|
|
|
// of child frames. That's OK because any reflow that updates these
|
|
|
|
// areas will invalidate the appropriate area, so any (mis)uses of
|
|
|
|
// this method will be fixed up.
|
2008-02-20 07:08:55 +00:00
|
|
|
|
2009-04-06 00:31:50 +00:00
|
|
|
if (mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) {
|
|
|
|
// there is an overflow rect, and it's not stored as deltas but as
|
|
|
|
// a separately-allocated rect
|
2008-02-20 07:08:55 +00:00
|
|
|
return *const_cast<nsIFrame*>(this)->GetOverflowAreaProperty(PR_FALSE);
|
2009-04-06 00:31:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the rect using deltas from the frame's border rect.
|
|
|
|
// Note that the mOverflow.mDeltas fields are unsigned, but we will often
|
|
|
|
// need to return negative values for the left and top, so take care
|
|
|
|
// to cast away the unsigned-ness.
|
|
|
|
return nsRect(-(PRInt32)mOverflow.mDeltas.mLeft,
|
|
|
|
-(PRInt32)mOverflow.mDeltas.mTop,
|
|
|
|
mRect.width + mOverflow.mDeltas.mRight +
|
|
|
|
mOverflow.mDeltas.mLeft,
|
|
|
|
mRect.height + mOverflow.mDeltas.mBottom +
|
|
|
|
mOverflow.mDeltas.mTop);
|
2004-08-26 00:07:56 +00:00
|
|
|
}
|
2008-09-16 01:51:52 +00:00
|
|
|
|
|
|
|
nsRect
|
|
|
|
nsIFrame::GetOverflowRectRelativeToParent() const
|
|
|
|
{
|
|
|
|
return GetOverflowRect() + mRect.TopLeft();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect
|
|
|
|
nsIFrame::GetOverflowRectRelativeToSelf() const
|
|
|
|
{
|
2008-10-01 00:51:05 +00:00
|
|
|
if (!(mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) ||
|
2008-09-16 01:51:52 +00:00
|
|
|
!GetStyleDisplay()->HasTransform())
|
|
|
|
return GetOverflowRect();
|
2009-07-30 02:48:13 +00:00
|
|
|
nsRect* preEffectsBBox = static_cast<nsRect*>
|
2008-09-16 01:51:52 +00:00
|
|
|
(GetProperty(nsGkAtoms::preEffectsBBoxProperty));
|
2009-07-30 02:48:13 +00:00
|
|
|
if (!preEffectsBBox)
|
|
|
|
return GetOverflowRect();
|
|
|
|
return *preEffectsBBox;
|
2008-09-16 01:51:52 +00:00
|
|
|
}
|
2008-10-21 07:42:28 +00:00
|
|
|
|
2004-01-10 05:36:32 +00:00
|
|
|
void
|
2008-08-20 06:45:29 +00:00
|
|
|
nsFrame::CheckInvalidateSizeChange(nsHTMLReflowMetrics& aNewDesiredSize)
|
2004-01-10 05:36:32 +00:00
|
|
|
{
|
2008-10-21 07:42:28 +00:00
|
|
|
nsIFrame::CheckInvalidateSizeChange(mRect, GetOverflowRect(),
|
|
|
|
nsSize(aNewDesiredSize.width, aNewDesiredSize.height));
|
2008-08-20 06:45:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsIFrame::CheckInvalidateSizeChange(const nsRect& aOldRect,
|
2008-10-21 07:42:28 +00:00
|
|
|
const nsRect& aOldOverflowRect,
|
|
|
|
const nsSize& aNewDesiredSize)
|
2008-08-20 06:45:29 +00:00
|
|
|
{
|
|
|
|
if (aNewDesiredSize.width == aOldRect.width &&
|
|
|
|
aNewDesiredSize.height == aOldRect.height)
|
2004-01-10 05:36:32 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Below, we invalidate the old frame area (or, in the case of
|
|
|
|
// outline, combined area) if the outline, border or background
|
|
|
|
// settings indicate that something other than the difference
|
|
|
|
// between the old and new areas needs to be painted. We are
|
|
|
|
// assuming that the difference between the old and new areas will
|
|
|
|
// be invalidated by some other means. That also means invalidating
|
|
|
|
// the old frame area is the same as invalidating the new frame area
|
|
|
|
// (since in either case the UNION of old and new areas will be
|
|
|
|
// invalidated)
|
|
|
|
|
|
|
|
// Invalidate the entire old frame+outline if the frame has an outline
|
2008-09-11 00:24:16 +00:00
|
|
|
PRBool anyOutlineOrEffects;
|
|
|
|
nsRect r = ComputeOutlineAndEffectsRect(this, &anyOutlineOrEffects,
|
|
|
|
aOldOverflowRect, PR_FALSE);
|
|
|
|
if (anyOutlineOrEffects) {
|
2008-08-20 06:45:29 +00:00
|
|
|
r.UnionRect(aOldOverflowRect, r);
|
2004-03-10 03:09:05 +00:00
|
|
|
Invalidate(r);
|
|
|
|
return;
|
2004-01-10 05:36:32 +00:00
|
|
|
}
|
|
|
|
|
2009-05-08 01:52:22 +00:00
|
|
|
// Invalidate the old frame border box if the frame has borders. Those
|
|
|
|
// borders may be moving.
|
2004-01-10 05:36:32 +00:00
|
|
|
const nsStyleBorder* border = GetStyleBorder();
|
2005-04-29 15:44:38 +00:00
|
|
|
NS_FOR_CSS_SIDES(side) {
|
2008-07-17 06:30:25 +00:00
|
|
|
if (border->GetActualBorderWidth(side) != 0) {
|
2009-05-08 01:52:22 +00:00
|
|
|
if ((side == NS_SIDE_LEFT || side == NS_SIDE_TOP) &&
|
|
|
|
!nsLayoutUtils::HasNonZeroCornerOnSide(border->mBorderRadius, side) &&
|
|
|
|
!border->GetBorderImage() &&
|
|
|
|
border->GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_SOLID) {
|
|
|
|
// We also need to be sure that the bottom-left or top-right
|
|
|
|
// corner is simple. For example, if the bottom or right border
|
|
|
|
// has a different color, we would need to invalidate the corner
|
|
|
|
// area. But that's OK because if there is a right or bottom border,
|
|
|
|
// we'll invalidate the entire border-box here anyway.
|
|
|
|
continue;
|
|
|
|
}
|
2008-08-20 06:45:29 +00:00
|
|
|
Invalidate(nsRect(0, 0, aOldRect.width, aOldRect.height));
|
2005-04-29 15:44:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-01-10 05:36:32 +00:00
|
|
|
}
|
|
|
|
|
2004-03-10 03:09:05 +00:00
|
|
|
// Invalidate the old frame background if the frame has a background
|
2004-01-10 05:36:32 +00:00
|
|
|
// whose position depends on the size of the frame
|
2009-02-20 05:29:21 +00:00
|
|
|
const nsStyleBackground *bg = GetStyleBackground();
|
|
|
|
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
|
|
|
const nsStyleBackground::Layer &layer = bg->mLayers[i];
|
2009-08-21 20:39:25 +00:00
|
|
|
if (!layer.mImage.IsEmpty() &&
|
2009-02-20 05:29:21 +00:00
|
|
|
(layer.mPosition.mXIsPercent || layer.mPosition.mYIsPercent)) {
|
|
|
|
Invalidate(nsRect(0, 0, aOldRect.width, aOldRect.height));
|
|
|
|
return;
|
|
|
|
}
|
2004-01-10 05:36:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-14 20:44:41 +00:00
|
|
|
// Define the MAX_FRAME_DEPTH to be the ContentSink's MAX_REFLOW_DEPTH plus
|
|
|
|
// 4 for the frames above the document's frames:
|
|
|
|
// the Viewport, GFXScroll, ScrollPort, and Canvas
|
|
|
|
#define MAX_FRAME_DEPTH (MAX_REFLOW_DEPTH+4)
|
1999-08-27 21:48:06 +00:00
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
|
|
|
|
nsHTMLReflowMetrics& aMetrics)
|
|
|
|
{
|
2001-09-14 20:44:41 +00:00
|
|
|
if (aReflowState.mReflowDepth > MAX_FRAME_DEPTH) {
|
2007-07-21 00:34:36 +00:00
|
|
|
mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
|
2009-04-06 00:31:50 +00:00
|
|
|
ClearOverflowRect();
|
1999-08-27 21:48:06 +00:00
|
|
|
aMetrics.width = 0;
|
|
|
|
aMetrics.height = 0;
|
|
|
|
aMetrics.ascent = 0;
|
2001-10-25 01:08:40 +00:00
|
|
|
aMetrics.mCarriedOutBottomMargin.Zero();
|
1999-12-06 15:49:53 +00:00
|
|
|
aMetrics.mOverflowArea.x = 0;
|
|
|
|
aMetrics.mOverflowArea.y = 0;
|
|
|
|
aMetrics.mOverflowArea.width = 0;
|
|
|
|
aMetrics.mOverflowArea.height = 0;
|
1999-08-27 21:48:06 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-07-21 00:34:36 +00:00
|
|
|
mState &= ~NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
|
1999-08-27 21:48:06 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2004-03-12 04:40:17 +00:00
|
|
|
/* virtual */ PRBool nsFrame::IsContainingBlock() const
|
1998-05-13 22:38:09 +00:00
|
|
|
{
|
2007-01-27 19:35:29 +00:00
|
|
|
const nsStyleDisplay* display = GetStyleDisplay();
|
|
|
|
|
|
|
|
// Absolute positioning causes |display->mDisplay| to be set to block,
|
|
|
|
// if needed.
|
|
|
|
return display->mDisplay == NS_STYLE_DISPLAY_BLOCK ||
|
|
|
|
display->mDisplay == NS_STYLE_DISPLAY_INLINE_BLOCK ||
|
|
|
|
display->mDisplay == NS_STYLE_DISPLAY_LIST_ITEM ||
|
|
|
|
display->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL;
|
1998-05-13 22:38:09 +00:00
|
|
|
}
|
|
|
|
|
2003-11-19 01:20:56 +00:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
|
1998-10-08 20:35:16 +00:00
|
|
|
PRInt32 nsFrame::ContentIndexInContainer(const nsIFrame* aFrame)
|
|
|
|
{
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 result = -1;
|
1998-10-08 20:35:16 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIContent* content = aFrame->GetContent();
|
2003-06-13 20:10:01 +00:00
|
|
|
if (content) {
|
2003-07-28 21:25:13 +00:00
|
|
|
nsIContent* parentContent = content->GetParent();
|
2003-06-13 20:10:01 +00:00
|
|
|
if (parentContent) {
|
2003-09-27 04:18:26 +00:00
|
|
|
result = parentContent->IndexOf(content);
|
1998-10-08 20:35:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2001-08-03 07:34:28 +00:00
|
|
|
/**
|
|
|
|
* List a frame tree to stdout. Meant to be called from gdb.
|
|
|
|
*/
|
|
|
|
void
|
2007-02-18 17:34:09 +00:00
|
|
|
DebugListFrameTree(nsIFrame* aFrame)
|
2001-08-03 07:34:28 +00:00
|
|
|
{
|
2007-02-18 17:34:09 +00:00
|
|
|
((nsFrame*)aFrame)->List(stdout, 0);
|
2001-08-03 07:34:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Debugging
|
1998-11-19 17:22:29 +00:00
|
|
|
NS_IMETHODIMP
|
2005-09-06 21:34:50 +00:00
|
|
|
nsFrame::List(FILE* out, PRInt32 aIndent) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-01-16 00:00:50 +00:00
|
|
|
IndentBy(out, aIndent);
|
|
|
|
ListTag(out);
|
2000-07-27 05:16:08 +00:00
|
|
|
#ifdef DEBUG_waterson
|
2007-07-08 07:08:04 +00:00
|
|
|
fprintf(out, " [parent=%p]", static_cast<void*>(mParent));
|
2000-07-27 05:16:08 +00:00
|
|
|
#endif
|
2003-06-19 23:44:01 +00:00
|
|
|
if (HasView()) {
|
2007-07-08 07:08:04 +00:00
|
|
|
fprintf(out, " [view=%p]", static_cast<void*>(GetView()));
|
1999-01-16 00:00:50 +00:00
|
|
|
}
|
1999-03-05 04:22:54 +00:00
|
|
|
fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
|
1999-01-16 00:00:50 +00:00
|
|
|
if (0 != mState) {
|
|
|
|
fprintf(out, " [state=%08x]", mState);
|
1998-05-18 16:53:09 +00:00
|
|
|
}
|
2005-03-23 03:35:08 +00:00
|
|
|
nsIFrame* prevInFlow = GetPrevInFlow();
|
|
|
|
nsIFrame* nextInFlow = GetNextInFlow();
|
|
|
|
if (nsnull != prevInFlow) {
|
2007-07-08 07:08:04 +00:00
|
|
|
fprintf(out, " prev-in-flow=%p", static_cast<void*>(prevInFlow));
|
2005-03-23 03:35:08 +00:00
|
|
|
}
|
|
|
|
if (nsnull != nextInFlow) {
|
2007-07-08 07:08:04 +00:00
|
|
|
fprintf(out, " next-in-flow=%p", static_cast<void*>(nextInFlow));
|
2005-03-23 03:35:08 +00:00
|
|
|
}
|
2007-07-08 07:08:04 +00:00
|
|
|
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
|
|
|
nsFrame* f = const_cast<nsFrame*>(this);
|
2009-04-06 00:31:50 +00:00
|
|
|
if (f->HasOverflowRect()) {
|
2008-02-20 07:08:55 +00:00
|
|
|
nsRect overflowArea = f->GetOverflowRect();
|
|
|
|
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
|
|
|
|
overflowArea.width, overflowArea.height);
|
2004-08-26 00:07:56 +00:00
|
|
|
}
|
1999-05-03 20:51:30 +00:00
|
|
|
fputs("\n", out);
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-11-19 17:22:29 +00:00
|
|
|
NS_IMETHODIMP
|
2001-11-14 01:33:42 +00:00
|
|
|
nsFrame::GetFrameName(nsAString& aResult) const
|
1998-11-19 17:22:29 +00:00
|
|
|
{
|
2001-11-14 01:33:42 +00:00
|
|
|
return MakeFrameName(NS_LITERAL_STRING("Frame"), aResult);
|
1998-11-19 17:22:29 +00:00
|
|
|
}
|
|
|
|
|
2004-04-04 01:48:16 +00:00
|
|
|
NS_IMETHODIMP_(nsFrameState)
|
|
|
|
nsFrame::GetDebugStateBits() const
|
|
|
|
{
|
|
|
|
// We'll ignore these flags for the purposes of comparing frame state:
|
|
|
|
//
|
|
|
|
// NS_FRAME_EXTERNAL_REFERENCE
|
|
|
|
// because this is set by the event state manager or the
|
|
|
|
// caret code when a frame is focused. Depending on whether
|
|
|
|
// or not the regression tests are run as the focused window
|
|
|
|
// will make this value vary randomly.
|
|
|
|
#define IRRELEVANT_FRAME_STATE_FLAGS NS_FRAME_EXTERNAL_REFERENCE
|
|
|
|
|
|
|
|
#define FRAME_STATE_MASK (~(IRRELEVANT_FRAME_STATE_FLAGS))
|
|
|
|
|
|
|
|
return GetStateBits() & FRAME_STATE_MASK;
|
|
|
|
}
|
|
|
|
|
1998-11-19 17:22:29 +00:00
|
|
|
nsresult
|
2001-11-14 01:33:42 +00:00
|
|
|
nsFrame::MakeFrameName(const nsAString& aType, nsAString& aResult) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2001-11-14 01:33:42 +00:00
|
|
|
aResult = aType;
|
2006-05-05 06:52:21 +00:00
|
|
|
if (mContent && !mContent->IsNodeOfType(nsINode::eTEXT)) {
|
2005-06-16 13:10:58 +00:00
|
|
|
nsAutoString buf;
|
|
|
|
mContent->Tag()->ToString(buf);
|
|
|
|
aResult.Append(NS_LITERAL_STRING("(") + buf + NS_LITERAL_STRING(")"));
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-11-19 17:22:29 +00:00
|
|
|
char buf[40];
|
1998-11-19 18:51:53 +00:00
|
|
|
PR_snprintf(buf, sizeof(buf), "(%d)", ContentIndexInContainer(this));
|
2003-11-01 10:57:41 +00:00
|
|
|
AppendASCIItoUTF16(buf, aResult);
|
1998-11-19 17:22:29 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-11-19 17:55:22 +00:00
|
|
|
void
|
|
|
|
nsFrame::XMLQuote(nsString& aString)
|
|
|
|
{
|
|
|
|
PRInt32 i, len = aString.Length();
|
|
|
|
for (i = 0; i < len; i++) {
|
1999-04-20 07:20:21 +00:00
|
|
|
PRUnichar ch = aString.CharAt(i);
|
1998-11-19 17:55:22 +00:00
|
|
|
if (ch == '<') {
|
2001-12-16 11:58:03 +00:00
|
|
|
nsAutoString tmp(NS_LITERAL_STRING("<"));
|
1998-11-19 17:55:22 +00:00
|
|
|
aString.Cut(i, 1);
|
|
|
|
aString.Insert(tmp, i);
|
|
|
|
len += 3;
|
|
|
|
i += 3;
|
|
|
|
}
|
|
|
|
else if (ch == '>') {
|
2001-12-16 11:58:03 +00:00
|
|
|
nsAutoString tmp(NS_LITERAL_STRING(">"));
|
1998-11-19 17:55:22 +00:00
|
|
|
aString.Cut(i, 1);
|
|
|
|
aString.Insert(tmp, i);
|
|
|
|
len += 3;
|
|
|
|
i += 3;
|
|
|
|
}
|
1999-02-04 16:28:36 +00:00
|
|
|
else if (ch == '\"') {
|
2001-12-16 11:58:03 +00:00
|
|
|
nsAutoString tmp(NS_LITERAL_STRING("""));
|
1998-11-19 17:55:22 +00:00
|
|
|
aString.Cut(i, 1);
|
|
|
|
aString.Insert(tmp, i);
|
|
|
|
len += 5;
|
|
|
|
i += 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-05-04 16:27:40 +00:00
|
|
|
#endif
|
1998-11-19 17:55:22 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::IsVisibleForPainting(nsDisplayListBuilder* aBuilder) {
|
|
|
|
if (!GetStyleVisibility()->IsVisible())
|
|
|
|
return PR_FALSE;
|
|
|
|
nsISelection* sel = aBuilder->GetBoundingSelection();
|
|
|
|
return !sel || IsVisibleInSelection(sel);
|
2001-01-27 14:09:34 +00:00
|
|
|
}
|
2000-05-04 08:35:42 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::IsVisibleForPainting() {
|
|
|
|
if (!GetStyleVisibility()->IsVisible())
|
|
|
|
return PR_FALSE;
|
2000-05-04 08:35:42 +00:00
|
|
|
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext* pc = PresContext();
|
2006-01-26 02:29:17 +00:00
|
|
|
if (!pc->IsRenderingOnlySelection())
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(pc->PresShell()));
|
|
|
|
if (selcon) {
|
|
|
|
nsCOMPtr<nsISelection> sel;
|
|
|
|
selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
|
|
|
getter_AddRefs(sel));
|
|
|
|
if (sel)
|
|
|
|
return IsVisibleInSelection(sel);
|
2001-03-08 02:46:44 +00:00
|
|
|
}
|
2006-01-26 02:29:17 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2001-03-08 02:46:44 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::IsVisibleInSelection(nsDisplayListBuilder* aBuilder) {
|
|
|
|
nsISelection* sel = aBuilder->GetBoundingSelection();
|
|
|
|
return !sel || IsVisibleInSelection(sel);
|
|
|
|
}
|
2001-03-08 02:46:44 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder) {
|
|
|
|
if (!GetStyleVisibility()->IsVisibleOrCollapsed())
|
|
|
|
return PR_FALSE;
|
|
|
|
nsISelection* sel = aBuilder->GetBoundingSelection();
|
|
|
|
return !sel || IsVisibleInSelection(sel);
|
|
|
|
}
|
2001-03-08 02:46:44 +00:00
|
|
|
|
2006-01-26 02:29:17 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::IsVisibleInSelection(nsISelection* aSelection)
|
|
|
|
{
|
|
|
|
if ((mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
|
|
|
|
PRBool vis;
|
|
|
|
nsresult rv = aSelection->ContainsNode(node, PR_TRUE, &vis);
|
|
|
|
return NS_FAILED(rv) || vis;
|
2001-03-08 02:46:44 +00:00
|
|
|
}
|
|
|
|
|
2003-11-10 23:36:06 +00:00
|
|
|
/* virtual */ PRBool
|
|
|
|
nsFrame::IsEmpty()
|
2001-10-25 01:08:40 +00:00
|
|
|
{
|
2003-11-10 23:36:06 +00:00
|
|
|
return PR_FALSE;
|
2001-10-25 01:08:40 +00:00
|
|
|
}
|
|
|
|
|
2006-02-27 04:15:05 +00:00
|
|
|
PRBool
|
|
|
|
nsIFrame::CachedIsEmpty()
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(!(GetStateBits() & NS_FRAME_IS_DIRTY),
|
|
|
|
"Must only be called on reflowed lines");
|
|
|
|
return IsEmpty();
|
|
|
|
}
|
|
|
|
|
2004-11-14 20:22:58 +00:00
|
|
|
/* virtual */ PRBool
|
2004-11-15 05:01:11 +00:00
|
|
|
nsFrame::IsSelfEmpty()
|
2004-11-14 20:22:58 +00:00
|
|
|
{
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2000-05-31 03:20:02 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon)
|
2000-05-04 08:35:42 +00:00
|
|
|
{
|
|
|
|
if (!aPresContext || !aSelCon)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2005-01-16 18:44:01 +00:00
|
|
|
|
|
|
|
nsIFrame *frame = this;
|
|
|
|
while (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)) {
|
2009-01-12 19:20:59 +00:00
|
|
|
nsITextControlFrame *tcf = do_QueryFrame(frame);
|
|
|
|
if (tcf) {
|
2006-02-21 00:49:04 +00:00
|
|
|
NS_IF_ADDREF(*aSelCon = tcf->GetOwnedSelectionController());
|
|
|
|
return NS_OK;
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
2005-01-16 18:44:01 +00:00
|
|
|
frame = frame->GetParent();
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
2005-01-16 18:44:01 +00:00
|
|
|
|
2006-02-21 00:49:04 +00:00
|
|
|
return CallQueryInterface(aPresContext->GetPresShell(), aSelCon);
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 20:47:33 +00:00
|
|
|
already_AddRefed<nsFrameSelection>
|
|
|
|
nsIFrame::GetFrameSelection()
|
|
|
|
{
|
|
|
|
nsFrameSelection* fs =
|
|
|
|
const_cast<nsFrameSelection*>(GetConstFrameSelection());
|
|
|
|
NS_IF_ADDREF(fs);
|
|
|
|
return fs;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nsFrameSelection*
|
|
|
|
nsIFrame::GetConstFrameSelection()
|
2006-02-21 00:49:04 +00:00
|
|
|
{
|
|
|
|
nsIFrame *frame = this;
|
|
|
|
while (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)) {
|
2009-01-12 19:20:59 +00:00
|
|
|
nsITextControlFrame *tcf = do_QueryFrame(frame);
|
|
|
|
if (tcf) {
|
2006-02-21 00:49:04 +00:00
|
|
|
return tcf->GetOwnedFrameSelection();
|
|
|
|
}
|
|
|
|
frame = frame->GetParent();
|
|
|
|
}
|
2000-05-04 08:35:42 +00:00
|
|
|
|
2007-11-22 20:47:33 +00:00
|
|
|
return PresContext()->PresShell()->ConstFrameSelection();
|
2006-02-21 00:49:04 +00:00
|
|
|
}
|
2000-05-04 08:35:42 +00:00
|
|
|
|
1999-11-01 22:12:45 +00:00
|
|
|
#ifdef NS_DEBUG
|
1998-11-19 17:22:29 +00:00
|
|
|
NS_IMETHODIMP
|
2009-02-10 04:36:54 +00:00
|
|
|
nsFrame::DumpRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
|
1998-11-19 17:22:29 +00:00
|
|
|
{
|
|
|
|
IndentBy(out, aIndent);
|
1999-02-08 17:56:00 +00:00
|
|
|
fprintf(out, "<frame va=\"%ld\" type=\"", PRUptrdiff(this));
|
1998-11-19 17:22:29 +00:00
|
|
|
nsAutoString name;
|
|
|
|
GetFrameName(name);
|
1998-11-19 17:55:22 +00:00
|
|
|
XMLQuote(name);
|
2006-02-03 14:18:39 +00:00
|
|
|
fputs(NS_LossyConvertUTF16toASCII(name).get(), out);
|
1999-02-08 17:56:00 +00:00
|
|
|
fprintf(out, "\" state=\"%d\" parent=\"%ld\">\n",
|
2004-04-04 01:48:16 +00:00
|
|
|
GetDebugStateBits(), PRUptrdiff(mParent));
|
1998-11-19 17:22:29 +00:00
|
|
|
|
|
|
|
aIndent++;
|
2009-02-10 04:36:54 +00:00
|
|
|
DumpBaseRegressionData(aPresContext, out, aIndent);
|
1998-11-19 17:22:29 +00:00
|
|
|
aIndent--;
|
|
|
|
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "</frame>\n");
|
1998-05-05 23:56:50 +00:00
|
|
|
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-11-19 17:22:29 +00:00
|
|
|
void
|
2009-02-10 04:36:54 +00:00
|
|
|
nsFrame::DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
|
1998-11-19 17:22:29 +00:00
|
|
|
{
|
2009-09-18 11:09:36 +00:00
|
|
|
if (GetNextSibling()) {
|
1998-11-19 17:22:29 +00:00
|
|
|
IndentBy(out, aIndent);
|
2009-09-18 11:09:36 +00:00
|
|
|
fprintf(out, "<next-sibling va=\"%ld\"/>\n", PRUptrdiff(GetNextSibling()));
|
1998-11-19 17:22:29 +00:00
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
if (HasView()) {
|
1998-11-19 17:22:29 +00:00
|
|
|
IndentBy(out, aIndent);
|
2003-06-28 11:48:14 +00:00
|
|
|
fprintf(out, "<view va=\"%ld\">\n", PRUptrdiff(GetView()));
|
1998-11-19 17:22:29 +00:00
|
|
|
aIndent++;
|
|
|
|
// XXX add in code to dump out view state too...
|
|
|
|
aIndent--;
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "</view>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
IndentBy(out, aIndent);
|
1999-02-08 17:56:00 +00:00
|
|
|
fprintf(out, "<bbox x=\"%d\" y=\"%d\" w=\"%d\" h=\"%d\"/>\n",
|
1998-11-19 17:22:29 +00:00
|
|
|
mRect.x, mRect.y, mRect.width, mRect.height);
|
|
|
|
|
|
|
|
// Now dump all of the children on all of the child lists
|
|
|
|
nsIFrame* kid;
|
|
|
|
nsIAtom* list = nsnull;
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
do {
|
2004-01-09 14:20:53 +00:00
|
|
|
kid = GetFirstChild(list);
|
|
|
|
if (kid) {
|
1998-11-19 17:22:29 +00:00
|
|
|
IndentBy(out, aIndent);
|
|
|
|
if (nsnull != list) {
|
|
|
|
nsAutoString listName;
|
|
|
|
list->ToString(listName);
|
|
|
|
fprintf(out, "<child-list name=\"");
|
1998-11-19 17:55:22 +00:00
|
|
|
XMLQuote(listName);
|
2006-02-03 14:18:39 +00:00
|
|
|
fputs(NS_LossyConvertUTF16toASCII(listName).get(), out);
|
1998-11-19 17:22:29 +00:00
|
|
|
fprintf(out, "\">\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(out, "<child-list>\n");
|
|
|
|
}
|
|
|
|
aIndent++;
|
2003-06-28 11:48:14 +00:00
|
|
|
while (kid) {
|
2009-08-20 21:52:48 +00:00
|
|
|
kid->DumpRegressionData(aPresContext, out, aIndent);
|
2003-06-28 11:48:14 +00:00
|
|
|
kid = kid->GetNextSibling();
|
1998-11-19 17:22:29 +00:00
|
|
|
}
|
|
|
|
aIndent--;
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "</child-list>\n");
|
|
|
|
}
|
2004-01-09 14:20:53 +00:00
|
|
|
list = GetAdditionalChildListName(listIndex++);
|
1998-11-19 17:22:29 +00:00
|
|
|
} while (nsnull != list);
|
|
|
|
}
|
1999-11-01 22:12:45 +00:00
|
|
|
#endif
|
1998-04-27 16:44:52 +00:00
|
|
|
|
2009-07-26 22:05:41 +00:00
|
|
|
void
|
|
|
|
nsIFrame::SetSelected(PRBool aSelected, SelectionType aType)
|
1999-05-20 00:52:00 +00:00
|
|
|
{
|
2009-07-26 22:05:41 +00:00
|
|
|
NS_ASSERTION(!GetPrevContinuation(),
|
|
|
|
"Should only be called on first in flow");
|
|
|
|
if (aType != nsISelectionController::SELECTION_NORMAL)
|
|
|
|
return;
|
2000-08-08 23:48:42 +00:00
|
|
|
|
2009-07-26 22:05:41 +00:00
|
|
|
// check whether style allows selection
|
|
|
|
PRBool selectable;
|
|
|
|
IsSelectable(&selectable, nsnull);
|
|
|
|
if (!selectable)
|
|
|
|
return;
|
2000-01-11 19:44:59 +00:00
|
|
|
|
2009-07-26 22:05:41 +00:00
|
|
|
for (nsIFrame* f = this; f; f = f->GetNextContinuation()) {
|
|
|
|
if (aSelected) {
|
|
|
|
AddStateBits(NS_FRAME_SELECTED_CONTENT);
|
|
|
|
} else {
|
|
|
|
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
1999-05-20 00:52:00 +00:00
|
|
|
}
|
2004-03-10 03:09:05 +00:00
|
|
|
|
2009-07-26 22:05:41 +00:00
|
|
|
// Repaint this frame subtree's entire area
|
|
|
|
InvalidateOverflowRect();
|
|
|
|
}
|
1998-12-14 18:34:14 +00:00
|
|
|
}
|
|
|
|
|
1999-01-22 18:58:14 +00:00
|
|
|
NS_IMETHODIMP
|
1999-04-26 04:02:04 +00:00
|
|
|
nsFrame::GetSelected(PRBool *aSelected) const
|
1998-12-14 18:34:14 +00:00
|
|
|
{
|
1999-01-22 18:58:14 +00:00
|
|
|
if (!aSelected )
|
1998-12-14 18:34:14 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
2007-10-10 00:00:05 +00:00
|
|
|
*aSelected = !!(mState & NS_FRAME_SELECTED_CONTENT);
|
1998-12-14 18:34:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-02-12 00:02:31 +00:00
|
|
|
NS_IMETHODIMP
|
2007-08-17 03:43:00 +00:00
|
|
|
nsFrame::GetPointFromOffset(PRInt32 inOffset, nsPoint* outPoint)
|
1999-02-12 00:02:31 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(outPoint != nsnull, "Null parameter");
|
2000-05-16 22:16:05 +00:00
|
|
|
nsPoint bottomLeft(0, 0);
|
1999-10-22 00:19:18 +00:00
|
|
|
if (mContent)
|
|
|
|
{
|
2003-07-28 21:25:13 +00:00
|
|
|
nsIContent* newContent = mContent->GetParent();
|
1999-10-22 00:19:18 +00:00
|
|
|
if (newContent){
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 newOffset = newContent->IndexOf(mContent);
|
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
PRBool isRTL = (NS_GET_EMBEDDING_LEVEL(this) & 1) == 1;
|
2008-09-15 15:40:25 +00:00
|
|
|
if ((!isRTL && inOffset > newOffset) ||
|
|
|
|
(isRTL && inOffset <= newOffset))
|
2003-06-28 11:48:14 +00:00
|
|
|
bottomLeft.x = GetRect().width;
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
1999-02-12 00:02:31 +00:00
|
|
|
*outPoint = bottomLeft;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-09-11 00:18:02 +00:00
|
|
|
nsFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset, PRBool inHint, PRInt32* outFrameContentOffset, nsIFrame **outChildFrame)
|
1999-02-12 00:02:31 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(outChildFrame && outFrameContentOffset, "Null parameter");
|
1999-09-11 00:18:02 +00:00
|
|
|
*outFrameContentOffset = (PRInt32)inHint;
|
2002-08-06 23:56:50 +00:00
|
|
|
//the best frame to reflect any given offset would be a visible frame if possible
|
|
|
|
//i.e. we are looking for a valid frame to place the blinking caret
|
2003-06-28 11:48:14 +00:00
|
|
|
nsRect rect = GetRect();
|
2002-08-06 23:56:50 +00:00
|
|
|
if (!rect.width || !rect.height)
|
|
|
|
{
|
|
|
|
//if we have a 0 width or height then lets look for another frame that possibly has
|
|
|
|
//the same content. If we have no frames in flow then just let us return 'this' frame
|
2004-09-14 02:28:03 +00:00
|
|
|
nsIFrame* nextFlow = GetNextInFlow();
|
|
|
|
if (nextFlow)
|
2002-08-06 23:56:50 +00:00
|
|
|
return nextFlow->GetChildFrameContainingOffset(inContentOffset, inHint, outFrameContentOffset, outChildFrame);
|
|
|
|
}
|
1999-02-12 00:02:31 +00:00
|
|
|
*outChildFrame = this;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-01-22 18:58:14 +00:00
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
//
|
|
|
|
// What I've pieced together about this routine:
|
|
|
|
// Starting with a block frame (from which a line frame can be gotten)
|
|
|
|
// and a line number, drill down and get the first/last selectable
|
|
|
|
// frame on that line, depending on aPos->mDirection.
|
|
|
|
// aOutSideLimit != 0 means ignore aLineStart, instead work from
|
|
|
|
// the end (if > 0) or beginning (if < 0).
|
|
|
|
//
|
1999-08-24 21:51:47 +00:00
|
|
|
nsresult
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
|
1999-10-26 04:44:41 +00:00
|
|
|
nsPeekOffsetStruct *aPos,
|
1999-07-15 18:19:03 +00:00
|
|
|
nsIFrame *aBlockFrame,
|
|
|
|
PRInt32 aLineStart,
|
1999-10-13 01:15:26 +00:00
|
|
|
PRInt8 aOutSideLimit
|
1999-07-15 18:19:03 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
//magic numbers aLineStart will be -1 for end of block 0 will be start of block
|
1999-10-13 01:15:26 +00:00
|
|
|
if (!aBlockFrame || !aPos)
|
1999-07-15 18:19:03 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-09-01 01:02:16 +00:00
|
|
|
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mResultFrame = nsnull;
|
|
|
|
aPos->mResultContent = nsnull;
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = (aPos->mDirection == eDirNext);
|
1999-10-13 01:15:26 +00:00
|
|
|
|
2008-10-30 19:17:59 +00:00
|
|
|
nsAutoLineIterator it = aBlockFrame->GetLineIterator();
|
|
|
|
if (!it)
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-07-15 18:19:03 +00:00
|
|
|
PRInt32 searchingLine = aLineStart;
|
2008-10-30 19:17:59 +00:00
|
|
|
PRInt32 countLines = it->GetNumLines();
|
1999-07-15 18:19:03 +00:00
|
|
|
if (aOutSideLimit > 0) //start at end
|
|
|
|
searchingLine = countLines;
|
2005-11-20 22:05:24 +00:00
|
|
|
else if (aOutSideLimit <0)//start at beginning
|
2000-05-11 01:04:39 +00:00
|
|
|
searchingLine = -1;//"next" will be 0
|
1999-07-15 18:19:03 +00:00
|
|
|
else
|
2000-05-11 01:04:39 +00:00
|
|
|
if ((aPos->mDirection == eDirPrevious && searchingLine == 0) ||
|
|
|
|
(aPos->mDirection == eDirNext && searchingLine >= (countLines -1) )){
|
1999-07-15 18:19:03 +00:00
|
|
|
//we need to jump to new block frame.
|
2000-05-11 01:04:39 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-07-15 18:19:03 +00:00
|
|
|
PRInt32 lineFrameCount;
|
|
|
|
nsIFrame *resultFrame = nsnull;
|
|
|
|
nsIFrame *farStoppingFrame = nsnull; //we keep searching until we find a "this" frame then we go to next line
|
|
|
|
nsIFrame *nearStoppingFrame = nsnull; //if we are backing up from edge, stop here
|
|
|
|
nsIFrame *firstFrame;
|
|
|
|
nsIFrame *lastFrame;
|
2002-08-06 23:56:50 +00:00
|
|
|
nsRect rect;
|
1999-07-15 18:19:03 +00:00
|
|
|
PRBool isBeforeFirstFrame, isAfterLastFrame;
|
|
|
|
PRBool found = PR_FALSE;
|
2008-10-30 19:17:59 +00:00
|
|
|
|
|
|
|
nsresult result = NS_OK;
|
1999-07-15 18:19:03 +00:00
|
|
|
while (!found)
|
|
|
|
{
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious)
|
1999-07-15 18:19:03 +00:00
|
|
|
searchingLine --;
|
|
|
|
else
|
|
|
|
searchingLine ++;
|
1999-10-13 01:15:26 +00:00
|
|
|
if ((aPos->mDirection == eDirPrevious && searchingLine < 0) ||
|
|
|
|
(aPos->mDirection == eDirNext && searchingLine >= countLines ))
|
1999-09-10 18:29:37 +00:00
|
|
|
{
|
2000-05-11 01:04:39 +00:00
|
|
|
//we need to jump to new block frame.
|
1999-09-10 18:29:37 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-10-12 23:25:19 +00:00
|
|
|
PRUint32 lineFlags;
|
|
|
|
result = it->GetLine(searchingLine, &firstFrame, &lineFrameCount,
|
2002-08-06 23:56:50 +00:00
|
|
|
rect, &lineFlags);
|
2002-08-20 22:42:26 +00:00
|
|
|
if (!lineFrameCount)
|
1999-09-10 18:29:37 +00:00
|
|
|
continue;
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_SUCCEEDED(result)){
|
|
|
|
lastFrame = firstFrame;
|
|
|
|
for (;lineFrameCount > 1;lineFrameCount --){
|
2000-05-11 01:04:39 +00:00
|
|
|
//result = lastFrame->GetNextSibling(&lastFrame, searchingLine);
|
2000-06-16 22:28:10 +00:00
|
|
|
result = it->GetNextSiblingOnLine(lastFrame, searchingLine);
|
2001-05-25 20:27:41 +00:00
|
|
|
if (NS_FAILED(result) || !lastFrame){
|
2005-10-17 00:03:05 +00:00
|
|
|
NS_ERROR("GetLine promised more frames than could be found");
|
2001-05-25 20:27:41 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-22 01:16:50 +00:00
|
|
|
GetLastLeaf(aPresContext, &lastFrame);
|
1999-07-15 18:19:03 +00:00
|
|
|
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirNext){
|
1999-07-15 18:19:03 +00:00
|
|
|
nearStoppingFrame = firstFrame;
|
|
|
|
farStoppingFrame = lastFrame;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
nearStoppingFrame = lastFrame;
|
|
|
|
farStoppingFrame = firstFrame;
|
|
|
|
}
|
1999-09-10 18:29:37 +00:00
|
|
|
nsPoint offset;
|
|
|
|
nsIView * view; //used for call of get offset from view
|
2004-12-26 19:48:54 +00:00
|
|
|
aBlockFrame->GetOffsetFromView(offset,&view);
|
1999-10-13 01:15:26 +00:00
|
|
|
nscoord newDesiredX = aPos->mDesiredX - offset.x;//get desired x into blockframe coordinates!
|
1999-09-10 18:29:37 +00:00
|
|
|
result = it->FindFrameAt(searchingLine, newDesiredX, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame);
|
2000-05-14 00:10:25 +00:00
|
|
|
if(NS_FAILED(result))
|
|
|
|
continue;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && resultFrame)
|
|
|
|
{
|
|
|
|
//check to see if this is ANOTHER blockframe inside the other one if so then call into its lines
|
2008-10-30 19:17:59 +00:00
|
|
|
nsAutoLineIterator newIt = resultFrame->GetLineIterator();
|
|
|
|
if (newIt)
|
1999-07-15 18:19:03 +00:00
|
|
|
{
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mResultFrame = resultFrame;
|
1999-09-01 21:40:16 +00:00
|
|
|
return NS_OK;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
//resultFrame is not a block frame
|
2008-10-30 19:17:59 +00:00
|
|
|
result = NS_ERROR_FAILURE;
|
1999-07-15 18:19:03 +00:00
|
|
|
|
2008-10-30 17:15:22 +00:00
|
|
|
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
2006-08-30 13:38:16 +00:00
|
|
|
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
|
|
|
aPresContext, resultFrame,
|
|
|
|
ePostOrder,
|
|
|
|
PR_FALSE, // aVisual
|
|
|
|
aPos->mScrollViewStop,
|
|
|
|
PR_FALSE // aFollowOOFs
|
|
|
|
);
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
nsIFrame *storeOldResultFrame = resultFrame;
|
|
|
|
while ( !found ){
|
1999-10-13 01:15:26 +00:00
|
|
|
nsPoint point;
|
|
|
|
point.x = aPos->mDesiredX;
|
2000-05-11 01:04:39 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsRect tempRect = resultFrame->GetRect();
|
2000-08-09 22:33:03 +00:00
|
|
|
nsPoint offset;
|
|
|
|
nsIView * view; //used for call of get offset from view
|
2004-12-26 19:48:54 +00:00
|
|
|
result = resultFrame->GetOffsetFromView(offset, &view);
|
2000-08-09 22:33:03 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
point.y = tempRect.height + offset.y;
|
|
|
|
|
2000-09-15 07:02:05 +00:00
|
|
|
//special check. if we allow non-text selection then we can allow a hit location to fall before a table.
|
|
|
|
//otherwise there is no way to get and click signal to fall before a table (it being a line iterator itself)
|
2001-12-18 01:29:49 +00:00
|
|
|
PRInt16 isEditor = 0;
|
2003-12-21 05:36:36 +00:00
|
|
|
nsIPresShell *shell = aPresContext->GetPresShell();
|
2000-09-15 07:02:05 +00:00
|
|
|
if (!shell)
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-12-18 01:29:49 +00:00
|
|
|
shell->GetSelectionFlags ( &isEditor );
|
|
|
|
isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
|
2000-09-15 07:02:05 +00:00
|
|
|
if ( isEditor )
|
|
|
|
{
|
2006-12-26 17:47:52 +00:00
|
|
|
if (resultFrame->GetType() == nsGkAtoms::tableOuterFrame)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
if (((point.x - offset.x + tempRect.x)<0) || ((point.x - offset.x+ tempRect.x)>tempRect.width))//off left/right side
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
nsIContent* content = resultFrame->GetContent();
|
|
|
|
if (content)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
nsIContent* parent = content->GetParent();
|
|
|
|
if (parent)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
aPos->mResultContent = parent;
|
|
|
|
aPos->mContentOffset = parent->IndexOf(content);
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = PR_FALSE;
|
2003-10-31 20:19:18 +00:00
|
|
|
if ((point.x - offset.x+ tempRect.x)>tempRect.width)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
aPos->mContentOffset++;//go to end of this frame
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = PR_TRUE;
|
2000-09-15 07:02:05 +00:00
|
|
|
}
|
2003-10-31 20:19:18 +00:00
|
|
|
//result frame is the result frames parent.
|
|
|
|
aPos->mResultFrame = resultFrame->GetParent();
|
|
|
|
return NS_POSITION_BEFORE_TABLE;
|
2000-09-15 07:02:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
if (!resultFrame->HasView())
|
2000-04-12 03:04:11 +00:00
|
|
|
{
|
2005-10-30 13:05:45 +00:00
|
|
|
nsIView* view;
|
|
|
|
nsPoint offset;
|
|
|
|
resultFrame->GetOffsetFromView(offset, &view);
|
2006-02-27 05:57:37 +00:00
|
|
|
ContentOffsets offsets =
|
|
|
|
resultFrame->GetContentOffsetsFromPoint(point - offset);
|
|
|
|
aPos->mResultContent = offsets.content;
|
|
|
|
aPos->mContentOffset = offsets.offset;
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = offsets.associateWithNext;
|
2006-02-27 05:57:37 +00:00
|
|
|
if (offsets.content)
|
2005-03-29 03:28:10 +00:00
|
|
|
{
|
|
|
|
PRBool selectable;
|
|
|
|
resultFrame->IsSelectable(&selectable, nsnull);
|
|
|
|
if (selectable)
|
|
|
|
{
|
|
|
|
found = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2000-04-12 03:04:11 +00:00
|
|
|
}
|
2005-03-29 03:28:10 +00:00
|
|
|
|
|
|
|
if (aPos->mDirection == eDirPrevious && (resultFrame == farStoppingFrame))
|
|
|
|
break;
|
|
|
|
if (aPos->mDirection == eDirNext && (resultFrame == nearStoppingFrame))
|
|
|
|
break;
|
|
|
|
//always try previous on THAT line if that fails go the other way
|
2008-10-30 17:15:22 +00:00
|
|
|
frameTraversal->Prev();
|
|
|
|
resultFrame = frameTraversal->CurrentItem();
|
|
|
|
if (!resultFrame)
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!found){
|
|
|
|
resultFrame = storeOldResultFrame;
|
2006-08-30 13:38:16 +00:00
|
|
|
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
|
|
|
aPresContext, resultFrame,
|
|
|
|
eLeaf,
|
|
|
|
PR_FALSE, // aVisual
|
|
|
|
aPos->mScrollViewStop,
|
|
|
|
PR_FALSE // aFollowOOFs
|
|
|
|
);
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
while ( !found ){
|
2006-02-27 05:57:37 +00:00
|
|
|
nsPoint point(aPos->mDesiredX, 0);
|
2005-09-04 20:04:23 +00:00
|
|
|
nsIView* view;
|
|
|
|
nsPoint offset;
|
|
|
|
resultFrame->GetOffsetFromView(offset, &view);
|
2006-02-27 05:57:37 +00:00
|
|
|
ContentOffsets offsets =
|
|
|
|
resultFrame->GetContentOffsetsFromPoint(point - offset);
|
|
|
|
aPos->mResultContent = offsets.content;
|
|
|
|
aPos->mContentOffset = offsets.offset;
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = offsets.associateWithNext;
|
2006-02-27 05:57:37 +00:00
|
|
|
if (offsets.content)
|
1999-10-13 01:15:26 +00:00
|
|
|
{
|
2005-03-29 03:28:10 +00:00
|
|
|
PRBool selectable;
|
|
|
|
resultFrame->IsSelectable(&selectable, nsnull);
|
|
|
|
if (selectable)
|
|
|
|
{
|
|
|
|
found = PR_TRUE;
|
|
|
|
if (resultFrame == farStoppingFrame)
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = PR_FALSE;
|
2005-03-29 03:28:10 +00:00
|
|
|
else
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = PR_TRUE;
|
1999-07-15 18:19:03 +00:00
|
|
|
break;
|
2005-03-29 03:28:10 +00:00
|
|
|
}
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
2005-03-29 03:28:10 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious && (resultFrame == nearStoppingFrame))
|
|
|
|
break;
|
|
|
|
if (aPos->mDirection == eDirNext && (resultFrame == farStoppingFrame))
|
|
|
|
break;
|
|
|
|
//previous didnt work now we try "next"
|
2008-10-30 17:15:22 +00:00
|
|
|
frameTraversal->Next();
|
|
|
|
nsIFrame *tempFrame = frameTraversal->CurrentItem();
|
|
|
|
if (!tempFrame)
|
2005-03-29 03:28:10 +00:00
|
|
|
break;
|
2008-10-30 17:15:22 +00:00
|
|
|
resultFrame = tempFrame;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mResultFrame = resultFrame;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
//we need to jump to new block frame.
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mAmount = eSelectLine;
|
|
|
|
aPos->mStartOffset = 0;
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = !(aPos->mDirection == eDirNext);
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
aPos->mStartOffset = -1;//start from end
|
2006-09-11 20:43:01 +00:00
|
|
|
return aBlockFrame->PeekOffset(aPos);
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-11-29 20:28:46 +00:00
|
|
|
nsPeekOffsetStruct nsIFrame::GetExtremeCaretPosition(PRBool aStart)
|
|
|
|
{
|
|
|
|
nsPeekOffsetStruct result;
|
|
|
|
|
2006-03-13 01:13:25 +00:00
|
|
|
FrameTarget targetFrame = DrillDownToSelectionFrame(this, !aStart);
|
|
|
|
FrameContentRange range = GetRangeForFrame(targetFrame.frame);
|
|
|
|
result.mResultContent = range.content;
|
|
|
|
result.mContentOffset = aStart ? range.start : range.end;
|
2006-07-13 06:06:29 +00:00
|
|
|
result.mAttachForward = (result.mContentOffset == range.start);
|
2004-11-29 20:28:46 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-08-18 17:09:16 +00:00
|
|
|
// Find the first (or last) descendant of the given frame
|
|
|
|
// which is either a block frame or a BRFrame.
|
2005-09-18 12:41:40 +00:00
|
|
|
static nsContentAndOffset
|
2005-08-18 17:09:16 +00:00
|
|
|
FindBlockFrameOrBR(nsIFrame* aFrame, nsDirection aDirection)
|
|
|
|
{
|
2005-09-18 12:41:40 +00:00
|
|
|
nsContentAndOffset result;
|
2006-03-01 19:28:42 +00:00
|
|
|
result.mContent = nsnull;
|
2008-02-23 10:54:29 +00:00
|
|
|
result.mOffset = 0;
|
2006-03-01 19:28:42 +00:00
|
|
|
|
2006-05-29 08:32:46 +00:00
|
|
|
if (aFrame->IsGeneratedContentFrame())
|
|
|
|
return result;
|
|
|
|
|
2006-03-01 19:28:42 +00:00
|
|
|
// Treat form controls as inline leaves
|
|
|
|
// XXX we really need a way to determine whether a frame is inline-level
|
2009-01-12 19:20:59 +00:00
|
|
|
nsIFormControlFrame* fcf = do_QueryFrame(aFrame);
|
|
|
|
if (fcf)
|
2006-03-01 19:28:42 +00:00
|
|
|
return result;
|
|
|
|
|
|
|
|
// Check the frame itself
|
2005-08-18 17:09:16 +00:00
|
|
|
// Fall through "special" block frames because their mContent is the content
|
|
|
|
// of the inline frames they were created from. The first/last child of
|
|
|
|
// such frames is the real block frame we're looking for.
|
2008-09-15 15:40:25 +00:00
|
|
|
if ((nsLayoutUtils::GetAsBlock(aFrame) && !(aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL)) ||
|
2006-12-26 17:47:52 +00:00
|
|
|
aFrame->GetType() == nsGkAtoms::brFrame) {
|
2005-09-18 12:41:40 +00:00
|
|
|
nsIContent* content = aFrame->GetContent();
|
|
|
|
result.mContent = content->GetParent();
|
2008-02-23 10:54:29 +00:00
|
|
|
// In some cases (bug 310589, bug 370174) we end up here with a null content.
|
|
|
|
// This probably shouldn't ever happen, but since it sometimes does, we want
|
|
|
|
// to avoid crashing here.
|
|
|
|
NS_ASSERTION(result.mContent, "Unexpected orphan content");
|
2008-02-22 21:21:15 +00:00
|
|
|
if (result.mContent)
|
|
|
|
result.mOffset = result.mContent->IndexOf(content) +
|
|
|
|
(aDirection == eDirPrevious ? 1 : 0);
|
2005-09-18 12:41:40 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2006-03-01 19:28:42 +00:00
|
|
|
// If this is a preformatted text frame, see if it ends with a newline
|
2005-12-06 00:32:52 +00:00
|
|
|
if (aFrame->HasTerminalNewline() &&
|
2008-08-12 08:31:56 +00:00
|
|
|
aFrame->GetStyleContext()->GetStyleText()->NewlineIsSignificant()) {
|
2005-09-18 12:41:40 +00:00
|
|
|
PRInt32 startOffset, endOffset;
|
|
|
|
aFrame->GetOffsets(startOffset, endOffset);
|
|
|
|
result.mContent = aFrame->GetContent();
|
|
|
|
result.mOffset = endOffset - (aDirection == eDirPrevious ? 0 : 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2006-03-01 19:28:42 +00:00
|
|
|
// Iterate over children and call ourselves recursively
|
2005-08-18 17:09:16 +00:00
|
|
|
if (aDirection == eDirPrevious) {
|
2009-09-18 11:09:36 +00:00
|
|
|
const nsFrameList& children(aFrame->GetChildList(nsnull));
|
2005-08-18 17:09:16 +00:00
|
|
|
nsIFrame* child = children.LastChild();
|
2005-09-18 12:41:40 +00:00
|
|
|
while(child && !result.mContent) {
|
|
|
|
result = FindBlockFrameOrBR(child, aDirection);
|
2005-08-18 17:09:16 +00:00
|
|
|
child = children.GetPrevSiblingFor(child);
|
|
|
|
}
|
|
|
|
} else { // eDirNext
|
|
|
|
nsIFrame* child = aFrame->GetFirstChild(nsnull);
|
2005-09-18 12:41:40 +00:00
|
|
|
while(child && !result.mContent) {
|
|
|
|
result = FindBlockFrameOrBR(child, aDirection);
|
2005-08-18 17:09:16 +00:00
|
|
|
child = child->GetNextSibling();
|
2000-05-16 22:48:28 +00:00
|
|
|
}
|
|
|
|
}
|
2005-09-18 12:41:40 +00:00
|
|
|
return result;
|
2000-05-16 22:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2006-09-11 20:43:01 +00:00
|
|
|
nsIFrame::PeekOffsetParagraph(nsPeekOffsetStruct *aPos)
|
2000-05-16 22:48:28 +00:00
|
|
|
{
|
2005-08-18 17:09:16 +00:00
|
|
|
nsIFrame* frame = this;
|
2005-09-18 12:41:40 +00:00
|
|
|
nsContentAndOffset blockFrameOrBR;
|
|
|
|
blockFrameOrBR.mContent = nsnull;
|
2005-08-18 17:09:16 +00:00
|
|
|
PRBool reachedBlockAncestor = PR_FALSE;
|
2000-05-16 22:48:28 +00:00
|
|
|
|
2005-08-18 17:09:16 +00:00
|
|
|
// Go through containing frames until reaching a block frame.
|
|
|
|
// In each step, search the previous (or next) siblings for the closest
|
|
|
|
// "stop frame" (a block frame or a BRFrame).
|
|
|
|
// If found, set it to be the selection boundray and abort.
|
|
|
|
|
|
|
|
if (aPos->mDirection == eDirPrevious) {
|
|
|
|
while (!reachedBlockAncestor) {
|
2005-08-28 08:20:34 +00:00
|
|
|
nsIFrame* parent = frame->GetParent();
|
2007-04-14 16:34:12 +00:00
|
|
|
// Treat a frame associated with the root content as if it were a block frame.
|
|
|
|
if (!frame->mContent || !frame->mContent->GetParent()) {
|
2005-08-28 08:20:34 +00:00
|
|
|
reachedBlockAncestor = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2009-09-18 11:09:36 +00:00
|
|
|
const nsFrameList& siblings(parent->GetChildList(nsnull));
|
2005-08-18 17:09:16 +00:00
|
|
|
nsIFrame* sibling = siblings.GetPrevSiblingFor(frame);
|
2005-09-18 12:41:40 +00:00
|
|
|
while (sibling && !blockFrameOrBR.mContent) {
|
|
|
|
blockFrameOrBR = FindBlockFrameOrBR(sibling, eDirPrevious);
|
2005-08-18 17:09:16 +00:00
|
|
|
sibling = siblings.GetPrevSiblingFor(sibling);
|
|
|
|
}
|
2005-09-18 12:41:40 +00:00
|
|
|
if (blockFrameOrBR.mContent) {
|
|
|
|
aPos->mResultContent = blockFrameOrBR.mContent;
|
|
|
|
aPos->mContentOffset = blockFrameOrBR.mOffset;
|
2000-05-16 22:48:28 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-08-28 08:20:34 +00:00
|
|
|
frame = parent;
|
2008-07-13 22:10:23 +00:00
|
|
|
reachedBlockAncestor = (nsLayoutUtils::GetAsBlock(frame) != nsnull);
|
2000-05-16 22:48:28 +00:00
|
|
|
}
|
2005-08-18 17:09:16 +00:00
|
|
|
if (reachedBlockAncestor) { // no "stop frame" found
|
|
|
|
aPos->mResultContent = frame->GetContent();
|
|
|
|
aPos->mContentOffset = 0;
|
|
|
|
}
|
|
|
|
} else { // eDirNext
|
|
|
|
while (!reachedBlockAncestor) {
|
2005-08-28 08:20:34 +00:00
|
|
|
nsIFrame* parent = frame->GetParent();
|
2007-04-14 16:34:12 +00:00
|
|
|
// Treat a frame associated with the root content as if it were a block frame.
|
|
|
|
if (!frame->mContent || !frame->mContent->GetParent()) {
|
2005-08-28 08:20:34 +00:00
|
|
|
reachedBlockAncestor = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2005-09-18 12:41:40 +00:00
|
|
|
nsIFrame* sibling = frame;
|
|
|
|
while (sibling && !blockFrameOrBR.mContent) {
|
|
|
|
blockFrameOrBR = FindBlockFrameOrBR(sibling, eDirNext);
|
2005-08-18 17:09:16 +00:00
|
|
|
sibling = sibling->GetNextSibling();
|
|
|
|
}
|
2005-09-18 12:41:40 +00:00
|
|
|
if (blockFrameOrBR.mContent) {
|
|
|
|
aPos->mResultContent = blockFrameOrBR.mContent;
|
|
|
|
aPos->mContentOffset = blockFrameOrBR.mOffset;
|
2005-08-18 17:09:16 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-08-28 08:20:34 +00:00
|
|
|
frame = parent;
|
2008-07-13 22:10:23 +00:00
|
|
|
reachedBlockAncestor = (nsLayoutUtils::GetAsBlock(frame) != nsnull);
|
2005-08-18 17:09:16 +00:00
|
|
|
}
|
|
|
|
if (reachedBlockAncestor) { // no "stop frame" found
|
|
|
|
aPos->mResultContent = frame->GetContent();
|
2005-08-28 08:20:34 +00:00
|
|
|
if (aPos->mResultContent)
|
|
|
|
aPos->mContentOffset = aPos->mResultContent->GetChildCount();
|
2000-05-16 22:48:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
// Determine movement direction relative to frame
|
|
|
|
static PRBool IsMovingInFrameDirection(nsIFrame* frame, nsDirection aDirection, PRBool aVisual)
|
|
|
|
{
|
|
|
|
PRBool isReverseDirection = aVisual ?
|
|
|
|
(NS_GET_EMBEDDING_LEVEL(frame) & 1) != (NS_GET_BASE_LEVEL(frame) & 1) : PR_FALSE;
|
|
|
|
return aDirection == (isReverseDirection ? eDirPrevious : eDirNext);
|
|
|
|
}
|
|
|
|
|
2006-09-11 08:03:28 +00:00
|
|
|
NS_IMETHODIMP
|
2006-09-11 20:43:01 +00:00
|
|
|
nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos)
|
1999-09-10 18:29:37 +00:00
|
|
|
{
|
2006-07-13 06:06:29 +00:00
|
|
|
if (!aPos)
|
1999-02-10 18:55:25 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
2006-07-13 06:06:29 +00:00
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
if (mState & NS_FRAME_IS_DIRTY)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
// Translate content offset to be relative to frame
|
|
|
|
FrameContentRange range = GetRangeForFrame(this);
|
|
|
|
PRInt32 offset = aPos->mStartOffset - range.start;
|
|
|
|
nsIFrame* current = this;
|
|
|
|
|
|
|
|
switch (aPos->mAmount) {
|
|
|
|
case eSelectCharacter:
|
|
|
|
{
|
|
|
|
PRBool eatingNonRenderableWS = PR_FALSE;
|
|
|
|
PRBool done = PR_FALSE;
|
|
|
|
|
|
|
|
while (!done) {
|
|
|
|
PRBool movingInFrameDirection =
|
|
|
|
IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
|
2005-09-19 05:16:25 +00:00
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
if (eatingNonRenderableWS)
|
|
|
|
done = current->PeekOffsetNoAmount(movingInFrameDirection, &offset);
|
|
|
|
else
|
|
|
|
done = current->PeekOffsetCharacter(movingInFrameDirection, &offset);
|
|
|
|
|
|
|
|
if (!done) {
|
|
|
|
PRBool jumpedLine;
|
|
|
|
result =
|
|
|
|
current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
|
|
|
|
aPos->mJumpLines, aPos->mScrollViewStop,
|
|
|
|
¤t, &offset, &jumpedLine);
|
2004-10-09 06:14:44 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
2006-09-11 20:43:01 +00:00
|
|
|
|
|
|
|
// 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 = PR_TRUE;
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
break;
|
2006-07-18 07:32:58 +00:00
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
case eSelectWord:
|
1999-09-25 23:33:02 +00:00
|
|
|
{
|
2006-09-11 20:43:01 +00:00
|
|
|
// wordSelectEatSpace means "are we looking for a boundary between whitespace
|
|
|
|
// and non-whitespace (in the direction we're moving in)".
|
|
|
|
// It is true when moving forward and looking for a beginning of a word, or
|
|
|
|
// when moving backwards and looking for an end of a word.
|
|
|
|
PRBool wordSelectEatSpace;
|
|
|
|
if (aPos->mWordMovementType != eDefaultBehavior) {
|
|
|
|
// aPos->mWordMovementType possible values:
|
|
|
|
// eEndWord: eat the space if we're moving backwards
|
|
|
|
// eStartWord: eat the space if we're moving forwards
|
|
|
|
wordSelectEatSpace = ((aPos->mWordMovementType == eEndWord) == (aPos->mDirection == eDirPrevious));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Use the hidden preference which is based on operating system behavior.
|
|
|
|
// This pref only affects whether moving forward by word should go to the end of this word or start of the next word.
|
|
|
|
// When going backwards, the start of the word is always used, on every operating system.
|
2007-07-02 23:36:59 +00:00
|
|
|
wordSelectEatSpace = aPos->mDirection == eDirNext &&
|
|
|
|
nsContentUtils::GetBoolPref("layout.word_select.eat_space_to_next_word");
|
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
|
2007-08-30 03:10:19 +00:00
|
|
|
// mSawBeforeType means "we already saw characters of the type
|
2006-09-11 20:43:01 +00:00
|
|
|
// before the boundary we're looking for". Examples:
|
|
|
|
// 1. If we're moving forward, looking for a word beginning (i.e. a boundary
|
|
|
|
// between whitespace and non-whitespace), then eatingWS==PR_TRUE means
|
|
|
|
// "we already saw some whitespace".
|
|
|
|
// 2. If we're moving backward, looking for a word beginning (i.e. a boundary
|
|
|
|
// between non-whitespace and whitespace), then eatingWS==PR_TRUE means
|
|
|
|
// "we already saw some non-whitespace".
|
2007-08-30 03:10:19 +00:00
|
|
|
PeekWordState state;
|
2006-09-11 20:43:01 +00:00
|
|
|
PRBool done = PR_FALSE;
|
|
|
|
while (!done) {
|
|
|
|
PRBool movingInFrameDirection =
|
|
|
|
IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
|
|
|
|
|
2007-08-30 03:10:19 +00:00
|
|
|
done = current->PeekOffsetWord(movingInFrameDirection, wordSelectEatSpace,
|
|
|
|
aPos->mIsKeyboardSelect, &offset, &state);
|
2006-09-11 20:43:01 +00:00
|
|
|
|
|
|
|
if (!done) {
|
|
|
|
nsIFrame* nextFrame;
|
|
|
|
PRInt32 nextFrameOffset;
|
|
|
|
PRBool jumpedLine;
|
|
|
|
result =
|
|
|
|
current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
|
|
|
|
aPos->mJumpLines, aPos->mScrollViewStop,
|
|
|
|
&nextFrame, &nextFrameOffset, &jumpedLine);
|
|
|
|
// We can't jump lines if we're looking for whitespace following
|
|
|
|
// non-whitespace, and we already encountered non-whitespace.
|
|
|
|
if (NS_FAILED(result) ||
|
2008-09-15 15:40:25 +00:00
|
|
|
(jumpedLine && !wordSelectEatSpace && state.mSawBeforeType)) {
|
2006-09-11 20:43:01 +00:00
|
|
|
done = PR_TRUE;
|
|
|
|
} else {
|
2007-11-08 04:33:28 +00:00
|
|
|
if (jumpedLine) {
|
|
|
|
state.mContext.Truncate();
|
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
current = nextFrame;
|
|
|
|
offset = nextFrameOffset;
|
|
|
|
// Jumping a line is equivalent to encountering whitespace
|
|
|
|
if (wordSelectEatSpace && jumpedLine)
|
2007-08-30 03:10:19 +00:00
|
|
|
state.SetSawBeforeType();
|
2006-09-11 20:43:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set outputs
|
|
|
|
range = GetRangeForFrame(current);
|
|
|
|
aPos->mResultFrame = current;
|
2006-07-18 07:32:58 +00:00
|
|
|
aPos->mResultContent = range.content;
|
2006-09-11 20:43:01 +00:00
|
|
|
// Output offset is relative to content, not frame
|
|
|
|
aPos->mContentOffset = offset < 0 ? range.end : range.start + offset;
|
2006-07-18 07:32:58 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-06-19 20:36:44 +00:00
|
|
|
case eSelectLine :
|
|
|
|
{
|
2008-10-30 19:17:59 +00:00
|
|
|
nsAutoLineIterator iter;
|
1999-06-19 20:36:44 +00:00
|
|
|
nsIFrame *blockFrame = this;
|
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
while (NS_FAILED(result)){
|
2008-10-09 10:22:30 +00:00
|
|
|
PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, aPos->mScrollViewStop, &blockFrame);
|
2001-05-24 01:10:19 +00:00
|
|
|
if (thisLine < 0)
|
|
|
|
return NS_ERROR_FAILURE;
|
2008-10-30 19:17:59 +00:00
|
|
|
iter = blockFrame->GetLineIterator();
|
|
|
|
NS_ASSERTION(iter, "GetLineNumber() succeeded but no block frame?");
|
|
|
|
result = NS_OK;
|
2001-05-24 01:10:19 +00:00
|
|
|
|
1999-09-01 21:40:16 +00:00
|
|
|
int edgeCase = 0;//no edge case. this should look at thisLine
|
2006-09-11 20:43:01 +00:00
|
|
|
|
1999-09-01 21:40:16 +00:00
|
|
|
PRBool doneLooping = PR_FALSE;//tells us when no more block frames hit.
|
2005-11-20 22:05:24 +00:00
|
|
|
//this part will find a frame or a block frame. if it's a block frame
|
1999-09-01 21:40:16 +00:00
|
|
|
//it will "drill down" to find a viable frame or it will return an error.
|
2001-04-12 23:38:32 +00:00
|
|
|
nsIFrame *lastFrame = this;
|
1999-09-01 21:40:16 +00:00
|
|
|
do {
|
2007-03-30 21:11:41 +00:00
|
|
|
result = nsFrame::GetNextPrevLineFromeBlockFrame(PresContext(),
|
2006-09-11 20:43:01 +00:00
|
|
|
aPos,
|
|
|
|
blockFrame,
|
|
|
|
thisLine,
|
|
|
|
edgeCase //start from thisLine
|
2001-04-12 23:38:32 +00:00
|
|
|
);
|
|
|
|
if (NS_SUCCEEDED(result) && (!aPos->mResultFrame || aPos->mResultFrame == lastFrame))//we came back to same spot! keep going
|
1999-09-22 06:12:44 +00:00
|
|
|
{
|
|
|
|
aPos->mResultFrame = nsnull;
|
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
thisLine--;
|
|
|
|
else
|
|
|
|
thisLine++;
|
|
|
|
}
|
2001-04-12 23:38:32 +00:00
|
|
|
else //if failure or success with different frame.
|
1999-09-22 06:12:44 +00:00
|
|
|
doneLooping = PR_TRUE; //do not continue with while loop
|
2001-04-12 23:38:32 +00:00
|
|
|
|
|
|
|
lastFrame = aPos->mResultFrame; //set last frame
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && aPos->mResultFrame
|
|
|
|
&& blockFrame != aPos->mResultFrame)// make sure block element is not the same as the one we had before
|
2000-12-27 00:22:25 +00:00
|
|
|
{
|
2001-06-20 04:40:17 +00:00
|
|
|
/* SPECIAL CHECK FOR TABLE NAVIGATION
|
|
|
|
tables need to navigate also and the frame that supports it is nsTableRowGroupFrame which is INSIDE
|
|
|
|
nsTableOuterFrame. if we have stumbled onto an nsTableOuter we need to drill into nsTableRowGroup
|
2005-11-20 22:05:24 +00:00
|
|
|
if we hit a header or footer that's ok just go into them,
|
2001-06-20 04:40:17 +00:00
|
|
|
*/
|
|
|
|
PRBool searchTableBool = PR_FALSE;
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aPos->mResultFrame->GetType() == nsGkAtoms::tableOuterFrame ||
|
|
|
|
aPos->mResultFrame->GetType() == nsGkAtoms::tableCellFrame)
|
2001-06-20 04:40:17 +00:00
|
|
|
{
|
2004-01-09 14:20:53 +00:00
|
|
|
nsIFrame *frame = aPos->mResultFrame->GetFirstChild(nsnull);
|
2001-06-20 04:40:17 +00:00
|
|
|
//got the table frame now
|
|
|
|
while(frame) //ok time to drill down to find iterator
|
|
|
|
{
|
2008-10-30 19:17:59 +00:00
|
|
|
iter = frame->GetLineIterator();
|
|
|
|
if (iter)
|
2001-06-20 04:40:17 +00:00
|
|
|
{
|
2004-09-02 05:02:53 +00:00
|
|
|
aPos->mResultFrame = frame;
|
|
|
|
searchTableBool = PR_TRUE;
|
2008-10-30 19:17:59 +00:00
|
|
|
result = NS_OK;
|
2004-09-02 05:02:53 +00:00
|
|
|
break; //while(frame)
|
2001-06-20 04:40:17 +00:00
|
|
|
}
|
2008-10-30 19:17:59 +00:00
|
|
|
result = NS_ERROR_FAILURE;
|
2004-09-02 05:02:53 +00:00
|
|
|
frame = frame->GetFirstChild(nsnull);
|
2001-06-20 04:40:17 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-30 19:17:59 +00:00
|
|
|
|
|
|
|
if (!searchTableBool) {
|
|
|
|
iter = aPos->mResultFrame->GetLineIterator();
|
|
|
|
result = iter ? NS_OK : NS_ERROR_FAILURE;
|
|
|
|
}
|
2001-04-12 23:38:32 +00:00
|
|
|
if (NS_SUCCEEDED(result) && iter)//we've struck another block element!
|
1999-09-01 21:40:16 +00:00
|
|
|
{
|
|
|
|
doneLooping = PR_FALSE;
|
1999-09-10 18:29:37 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious)
|
1999-09-01 21:40:16 +00:00
|
|
|
edgeCase = 1;//far edge, search from end backwards
|
|
|
|
else
|
|
|
|
edgeCase = -1;//near edge search from beginning onwards
|
|
|
|
thisLine=0;//this line means nothing now.
|
|
|
|
//everything else means something so keep looking "inside" the block
|
1999-09-10 18:29:37 +00:00
|
|
|
blockFrame = aPos->mResultFrame;
|
1999-09-01 21:40:16 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
2001-04-12 23:38:32 +00:00
|
|
|
{
|
1999-09-01 21:40:16 +00:00
|
|
|
result = NS_OK;//THIS is to mean that everything is ok to the containing while loop
|
2001-04-12 23:38:32 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-09-01 21:40:16 +00:00
|
|
|
}
|
2001-04-12 23:38:32 +00:00
|
|
|
} while (!doneLooping);
|
1999-06-19 20:36:44 +00:00
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
return result;
|
1999-06-19 20:36:44 +00:00
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
|
|
|
|
case eSelectParagraph:
|
2006-09-11 20:43:01 +00:00
|
|
|
return PeekOffsetParagraph(aPos);
|
2000-05-16 22:48:28 +00:00
|
|
|
|
1999-09-07 23:40:17 +00:00
|
|
|
case eSelectBeginLine:
|
|
|
|
case eSelectEndLine:
|
|
|
|
{
|
2006-03-13 01:13:25 +00:00
|
|
|
// Adjusted so that the caret can't get confused when content changes
|
|
|
|
nsIFrame* blockFrame = AdjustFrameForSelectionStyles(this);
|
2008-10-09 10:22:30 +00:00
|
|
|
PRInt32 thisLine = nsFrame::GetLineNumber(blockFrame, aPos->mScrollViewStop, &blockFrame);
|
2006-03-20 09:20:49 +00:00
|
|
|
if (thisLine < 0)
|
2006-03-13 01:13:25 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2008-10-30 19:17:59 +00:00
|
|
|
nsAutoLineIterator it = blockFrame->GetLineIterator();
|
|
|
|
NS_ASSERTION(it, "GetLineNumber() succeeded but no block frame?");
|
2000-05-16 22:48:28 +00:00
|
|
|
|
1999-09-07 23:40:17 +00:00
|
|
|
PRInt32 lineFrameCount;
|
|
|
|
nsIFrame *firstFrame;
|
2006-03-13 01:13:25 +00:00
|
|
|
nsRect usedRect;
|
1999-10-12 23:25:19 +00:00
|
|
|
PRUint32 lineFlags;
|
2006-03-13 01:13:25 +00:00
|
|
|
nsIFrame* baseFrame = nsnull;
|
2006-08-03 06:24:11 +00:00
|
|
|
PRBool endOfLine = (eSelectEndLine == aPos->mAmount);
|
|
|
|
|
|
|
|
#ifdef IBMBIDI
|
2007-03-30 21:11:41 +00:00
|
|
|
if (aPos->mVisual && PresContext()->BidiEnabled()) {
|
2008-10-30 19:17:59 +00:00
|
|
|
PRBool lineIsRTL = it->GetDirection();
|
2006-08-03 06:24:11 +00:00
|
|
|
PRBool isReordered;
|
|
|
|
nsIFrame *lastFrame;
|
|
|
|
result = it->CheckLineOrder(thisLine, &isReordered, &firstFrame, &lastFrame);
|
|
|
|
baseFrame = endOfLine ? lastFrame : firstFrame;
|
2007-08-29 07:22:42 +00:00
|
|
|
if (baseFrame) {
|
|
|
|
nsBidiLevel embeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(baseFrame);
|
|
|
|
// If the direction of the frame on the edge is opposite to that of the line,
|
|
|
|
// we'll need to drill down to its opposite end, so reverse endOfLine.
|
|
|
|
if ((embeddingLevel & 1) == !lineIsRTL)
|
|
|
|
endOfLine = !endOfLine;
|
|
|
|
}
|
2006-08-03 06:24:11 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
it->GetLine(thisLine, &firstFrame, &lineFrameCount, usedRect, &lineFlags);
|
|
|
|
|
|
|
|
nsIFrame* frame = firstFrame;
|
|
|
|
for (PRInt32 count = lineFrameCount; count;
|
|
|
|
--count, frame = frame->GetNextSibling()) {
|
|
|
|
if (!frame->IsGeneratedContentFrame()) {
|
|
|
|
baseFrame = frame;
|
|
|
|
if (!endOfLine)
|
|
|
|
break;
|
|
|
|
}
|
2006-03-13 01:13:25 +00:00
|
|
|
}
|
1999-09-07 23:40:17 +00:00
|
|
|
}
|
2006-03-13 01:13:25 +00:00
|
|
|
if (!baseFrame)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
FrameTarget targetFrame = DrillDownToSelectionFrame(baseFrame,
|
|
|
|
endOfLine);
|
|
|
|
FrameContentRange range = GetRangeForFrame(targetFrame.frame);
|
|
|
|
aPos->mResultContent = range.content;
|
|
|
|
aPos->mContentOffset = endOfLine ? range.end : range.start;
|
2006-08-03 06:24:11 +00:00
|
|
|
aPos->mResultFrame = targetFrame.frame;
|
2006-07-13 06:06:29 +00:00
|
|
|
aPos->mAttachForward = (aPos->mContentOffset == range.start);
|
2006-03-13 01:13:25 +00:00
|
|
|
if (!range.content)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return NS_OK;
|
2000-05-16 22:48:28 +00:00
|
|
|
}
|
1999-10-22 00:19:18 +00:00
|
|
|
|
1999-06-19 20:36:44 +00:00
|
|
|
default:
|
|
|
|
{
|
2006-09-11 20:43:01 +00:00
|
|
|
NS_ASSERTION(PR_FALSE, "Invalid amount");
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
|
|
|
|
{
|
|
|
|
NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
|
|
|
|
// Sure, we can stop right here.
|
|
|
|
return PR_TRUE;
|
2006-09-11 06:39:56 +00:00
|
|
|
}
|
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
PRBool
|
|
|
|
nsFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
|
|
|
|
{
|
|
|
|
NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
|
|
|
|
PRInt32 startOffset = *aOffset;
|
|
|
|
// A negative offset means "end of frame", which in our case means offset 1.
|
|
|
|
if (startOffset < 0)
|
|
|
|
startOffset = 1;
|
|
|
|
if (aForward == (startOffset == 0)) {
|
|
|
|
// We're before the frame and moving forward, or after it and moving backwards:
|
|
|
|
// skip to the other side and we're done.
|
|
|
|
*aOffset = 1 - startOffset;
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsFrame::PeekOffsetWord(PRBool aForward, PRBool aWordSelectEatSpace, PRBool aIsKeyboardSelect,
|
2007-08-30 03:10:19 +00:00
|
|
|
PRInt32* aOffset, PeekWordState* aState)
|
2006-09-11 20:43:01 +00:00
|
|
|
{
|
|
|
|
NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
|
|
|
|
PRInt32 startOffset = *aOffset;
|
2007-11-08 04:33:28 +00:00
|
|
|
// This isn't text, so truncate the context
|
|
|
|
aState->mContext.Truncate();
|
2006-09-11 20:43:01 +00:00
|
|
|
if (startOffset < 0)
|
|
|
|
startOffset = 1;
|
|
|
|
if (aForward == (startOffset == 0)) {
|
|
|
|
// We're before the frame and moving forward, or after it and moving backwards.
|
|
|
|
// If we're looking for non-whitespace, we found it (without skipping this frame).
|
2007-08-30 03:10:19 +00:00
|
|
|
if (!aState->mAtStart) {
|
|
|
|
if (aState->mLastCharWasPunctuation) {
|
|
|
|
// We're not punctuation, so this is a punctuation boundary.
|
2008-03-03 08:37:34 +00:00
|
|
|
if (BreakWordBetweenPunctuation(aState, aForward, PR_FALSE, PR_FALSE, aIsKeyboardSelect))
|
2007-08-30 03:10:19 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
} else {
|
|
|
|
// This is not a punctuation boundary.
|
|
|
|
if (aWordSelectEatSpace && aState->mSawBeforeType)
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
// Otherwise skip to the other side and note that we encountered non-whitespace.
|
|
|
|
*aOffset = 1 - startOffset;
|
2008-03-03 08:37:34 +00:00
|
|
|
aState->Update(PR_FALSE, // not punctuation
|
|
|
|
PR_FALSE // not whitespace
|
|
|
|
);
|
2006-09-11 20:43:01 +00:00
|
|
|
if (!aWordSelectEatSpace)
|
2007-08-30 03:10:19 +00:00
|
|
|
aState->SetSawBeforeType();
|
2006-09-11 20:43:01 +00:00
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2000-07-26 11:31:12 +00:00
|
|
|
|
2007-08-30 03:10:19 +00:00
|
|
|
PRBool
|
2008-03-03 08:37:34 +00:00
|
|
|
nsFrame::BreakWordBetweenPunctuation(const PeekWordState* aState,
|
|
|
|
PRBool aForward,
|
|
|
|
PRBool aPunctAfter, PRBool aWhitespaceAfter,
|
|
|
|
PRBool aIsKeyboardSelect)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aPunctAfter != aState->mLastCharWasPunctuation,
|
|
|
|
"Call this only at punctuation boundaries");
|
|
|
|
if (aState->mLastCharWasWhitespace) {
|
|
|
|
// We always stop between whitespace and punctuation
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-08-30 03:10:19 +00:00
|
|
|
if (!nsContentUtils::GetBoolPref("layout.word_select.stop_at_punctuation")) {
|
2008-03-03 08:37:34 +00:00
|
|
|
// When this pref is false, we never stop at a punctuation boundary unless
|
|
|
|
// it's after whitespace
|
2007-08-30 03:10:19 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
if (!aIsKeyboardSelect) {
|
|
|
|
// mouse caret movement (e.g. word selection) always stops at every punctuation boundary
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2008-03-03 08:37:34 +00:00
|
|
|
PRBool afterPunct = aForward ? aState->mLastCharWasPunctuation : aPunctAfter;
|
|
|
|
if (!afterPunct) {
|
|
|
|
// keyboard caret movement only stops after punctuation (in content order)
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
// Stop only if we've seen some non-punctuation since the last whitespace;
|
|
|
|
// don't stop after punctuation that follows whitespace.
|
|
|
|
return aState->mSeenNonPunctuationSinceWhitespace;
|
2007-08-30 03:10:19 +00:00
|
|
|
}
|
|
|
|
|
2000-07-26 11:31:12 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::CheckVisibility(nsPresContext* , PRInt32 , PRInt32 , PRBool , PRBool *, PRBool *)
|
2000-07-26 11:31:12 +00:00
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
PRInt32
|
2008-10-09 10:22:30 +00:00
|
|
|
nsFrame::GetLineNumber(nsIFrame *aFrame, PRBool aLockScroll, nsIFrame** aContainingBlock)
|
1999-10-22 00:19:18 +00:00
|
|
|
{
|
2006-03-20 09:20:49 +00:00
|
|
|
NS_ASSERTION(aFrame, "null aFrame");
|
2007-03-30 21:11:41 +00:00
|
|
|
nsFrameManager* frameManager = aFrame->PresContext()->FrameManager();
|
1999-10-22 00:19:18 +00:00
|
|
|
nsIFrame *blockFrame = aFrame;
|
|
|
|
nsIFrame *thisBlock;
|
2008-10-30 19:17:59 +00:00
|
|
|
nsAutoLineIterator it;
|
1999-10-22 00:19:18 +00:00
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
|
|
|
while (NS_FAILED(result) && blockFrame)
|
|
|
|
{
|
|
|
|
thisBlock = blockFrame;
|
2006-03-20 09:20:49 +00:00
|
|
|
if (thisBlock->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
|
|
|
|
//if we are searching for a frame that is not in flow we will not find it.
|
|
|
|
//we must instead look for its placeholder
|
2007-10-02 05:57:45 +00:00
|
|
|
if (thisBlock->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
|
|
|
|
// abspos continuations don't have placeholders, get the fif
|
|
|
|
thisBlock = thisBlock->GetFirstInFlow();
|
|
|
|
}
|
2006-03-20 09:20:49 +00:00
|
|
|
thisBlock = frameManager->GetPlaceholderFrameFor(thisBlock);
|
|
|
|
if (!thisBlock)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
blockFrame = thisBlock->GetParent();
|
2003-06-28 11:48:14 +00:00
|
|
|
result = NS_OK;
|
|
|
|
if (blockFrame) {
|
2008-10-09 10:22:30 +00:00
|
|
|
if (aLockScroll && blockFrame->GetType() == nsGkAtoms::scrollFrame)
|
|
|
|
return -1;
|
2008-10-30 19:17:59 +00:00
|
|
|
it = blockFrame->GetLineIterator();
|
|
|
|
if (!it)
|
|
|
|
result = NS_ERROR_FAILURE;
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!blockFrame || !it)
|
2006-03-20 09:20:49 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (aContainingBlock)
|
|
|
|
*aContainingBlock = blockFrame;
|
2008-10-30 19:17:59 +00:00
|
|
|
return it->FindLineContaining(thisBlock);
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
1999-09-22 04:12:23 +00:00
|
|
|
|
2006-08-07 11:24:57 +00:00
|
|
|
nsresult
|
2006-09-11 20:43:01 +00:00
|
|
|
nsIFrame::GetFrameFromDirection(nsDirection aDirection, PRBool aVisual,
|
|
|
|
PRBool aJumpLines, PRBool aScrollViewStop,
|
|
|
|
nsIFrame** aOutFrame, PRInt32* aOutOffset, PRBool* aOutJumpedLine)
|
2008-10-30 19:17:59 +00:00
|
|
|
{
|
|
|
|
nsresult result;
|
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
if (!aOutFrame || !aOutOffset || !aOutJumpedLine)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext* presContext = PresContext();
|
2006-09-11 20:43:01 +00:00
|
|
|
*aOutFrame = nsnull;
|
|
|
|
*aOutOffset = 0;
|
|
|
|
*aOutJumpedLine = PR_FALSE;
|
|
|
|
|
2006-03-23 08:30:30 +00:00
|
|
|
// Find the prev/next selectable frame
|
|
|
|
PRBool selectable = PR_FALSE;
|
|
|
|
nsIFrame *traversedFrame = this;
|
|
|
|
while (!selectable) {
|
|
|
|
nsIFrame *blockFrame;
|
2001-03-09 03:29:00 +00:00
|
|
|
|
2008-10-09 10:22:30 +00:00
|
|
|
PRInt32 thisLine = nsFrame::GetLineNumber(traversedFrame, aScrollViewStop, &blockFrame);
|
2006-03-20 09:20:49 +00:00
|
|
|
if (thisLine < 0)
|
2001-03-09 03:29:00 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2008-10-30 19:17:59 +00:00
|
|
|
|
|
|
|
nsAutoLineIterator it = blockFrame->GetLineIterator();
|
|
|
|
NS_ASSERTION(it, "GetLineNumber() succeeded but no block frame?");
|
2006-03-20 09:20:49 +00:00
|
|
|
|
2006-07-12 11:22:18 +00:00
|
|
|
PRBool atLineEdge;
|
2006-03-23 08:30:30 +00:00
|
|
|
nsIFrame *firstFrame;
|
|
|
|
nsIFrame *lastFrame;
|
|
|
|
#ifdef IBMBIDI
|
2006-09-11 20:43:01 +00:00
|
|
|
if (aVisual && presContext->BidiEnabled()) {
|
2008-10-30 19:17:59 +00:00
|
|
|
PRBool lineIsRTL = it->GetDirection();
|
2006-07-12 11:22:18 +00:00
|
|
|
PRBool isReordered;
|
|
|
|
result = it->CheckLineOrder(thisLine, &isReordered, &firstFrame, &lastFrame);
|
2006-09-11 20:43:01 +00:00
|
|
|
nsIFrame** framePtr = aDirection == eDirPrevious ? &firstFrame : &lastFrame;
|
2006-08-04 05:40:57 +00:00
|
|
|
if (*framePtr) {
|
|
|
|
nsBidiLevel embeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(*framePtr);
|
2008-09-15 15:40:25 +00:00
|
|
|
if ((((embeddingLevel & 1) && lineIsRTL) || (!(embeddingLevel & 1) && !lineIsRTL)) ==
|
2006-09-11 20:43:01 +00:00
|
|
|
(aDirection == eDirPrevious)) {
|
|
|
|
nsFrame::GetFirstLeaf(presContext, framePtr);
|
2006-08-04 05:40:57 +00:00
|
|
|
} else {
|
2006-09-11 20:43:01 +00:00
|
|
|
nsFrame::GetLastLeaf(presContext, framePtr);
|
2006-08-04 05:40:57 +00:00
|
|
|
}
|
|
|
|
atLineEdge = *framePtr == traversedFrame;
|
2006-07-12 11:22:18 +00:00
|
|
|
} else {
|
2006-08-04 05:40:57 +00:00
|
|
|
atLineEdge = PR_TRUE;
|
2006-07-12 11:22:18 +00:00
|
|
|
}
|
|
|
|
} else
|
2006-03-23 08:30:30 +00:00
|
|
|
#endif
|
2001-03-09 03:29:00 +00:00
|
|
|
{
|
2006-07-12 11:22:18 +00:00
|
|
|
nsRect nonUsedRect;
|
|
|
|
PRInt32 lineFrameCount;
|
|
|
|
PRUint32 lineFlags;
|
2006-03-23 08:30:30 +00:00
|
|
|
result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect,
|
2001-03-09 03:29:00 +00:00
|
|
|
&lineFlags);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
if (aDirection == eDirPrevious) {
|
|
|
|
nsFrame::GetFirstLeaf(presContext, &firstFrame);
|
2006-07-12 11:22:18 +00:00
|
|
|
atLineEdge = firstFrame == traversedFrame;
|
|
|
|
} else { // eDirNext
|
|
|
|
lastFrame = firstFrame;
|
|
|
|
for (;lineFrameCount > 1;lineFrameCount --){
|
|
|
|
result = it->GetNextSiblingOnLine(lastFrame, thisLine);
|
|
|
|
if (NS_FAILED(result) || !lastFrame){
|
2009-08-14 14:09:00 +00:00
|
|
|
NS_ERROR("should not be reached nsFrame\n");
|
2006-07-12 11:22:18 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
nsFrame::GetLastLeaf(presContext, &lastFrame);
|
2006-07-12 11:22:18 +00:00
|
|
|
atLineEdge = lastFrame == traversedFrame;
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
if (atLineEdge) {
|
|
|
|
*aOutJumpedLine = PR_TRUE;
|
|
|
|
if (!aJumpLines)
|
|
|
|
return NS_ERROR_FAILURE; //we are done. cannot jump lines
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
2006-09-11 20:43:01 +00:00
|
|
|
|
2008-10-30 17:15:22 +00:00
|
|
|
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
2006-03-23 08:30:30 +00:00
|
|
|
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
2006-09-11 20:43:01 +00:00
|
|
|
presContext, traversedFrame,
|
2006-08-30 13:38:16 +00:00
|
|
|
eLeaf,
|
2006-09-11 20:43:01 +00:00
|
|
|
aVisual && presContext->BidiEnabled(),
|
|
|
|
aScrollViewStop,
|
2006-08-30 13:38:16 +00:00
|
|
|
PR_TRUE // aFollowOOFs
|
|
|
|
);
|
2006-03-23 08:30:30 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
2006-09-11 20:43:01 +00:00
|
|
|
if (aDirection == eDirNext)
|
2008-10-30 17:15:22 +00:00
|
|
|
frameTraversal->Next();
|
2006-09-11 20:43:01 +00:00
|
|
|
else
|
2008-10-30 17:15:22 +00:00
|
|
|
frameTraversal->Prev();
|
2006-09-11 20:43:01 +00:00
|
|
|
|
2008-10-30 17:15:22 +00:00
|
|
|
traversedFrame = frameTraversal->CurrentItem();
|
|
|
|
if (!traversedFrame)
|
|
|
|
return NS_ERROR_FAILURE;
|
2006-03-23 08:30:30 +00:00
|
|
|
traversedFrame->IsSelectable(&selectable, nsnull);
|
|
|
|
} // while (!selectable)
|
2006-09-11 20:43:01 +00:00
|
|
|
|
|
|
|
*aOutOffset = (aDirection == eDirNext) ? 0 : -1;
|
|
|
|
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
2006-09-11 20:43:01 +00:00
|
|
|
if (aVisual) {
|
2006-04-08 14:45:48 +00:00
|
|
|
PRUint8 newLevel = NS_GET_EMBEDDING_LEVEL(traversedFrame);
|
|
|
|
PRUint8 newBaseLevel = NS_GET_BASE_LEVEL(traversedFrame);
|
|
|
|
if ((newLevel & 1) != (newBaseLevel & 1)) // The new frame is reverse-direction, go to the other end
|
2006-09-11 20:43:01 +00:00
|
|
|
*aOutOffset = -1 - *aOutOffset;
|
2006-04-08 14:45:48 +00:00
|
|
|
}
|
2001-03-09 03:29:00 +00:00
|
|
|
#endif
|
2006-09-11 20:43:01 +00:00
|
|
|
*aOutFrame = traversedFrame;
|
1999-10-22 00:19:18 +00:00
|
|
|
return NS_OK;
|
1999-02-02 00:23:40 +00:00
|
|
|
}
|
|
|
|
|
2004-11-03 16:16:57 +00:00
|
|
|
nsIView* nsIFrame::GetClosestView(nsPoint* aOffset) const
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
2004-11-03 16:16:57 +00:00
|
|
|
nsPoint offset(0,0);
|
|
|
|
for (const nsIFrame *f = this; f; f = f->GetParent()) {
|
|
|
|
if (f->HasView()) {
|
|
|
|
if (aOffset)
|
|
|
|
*aOffset = offset;
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return f->GetView();
|
2004-11-03 16:16:57 +00:00
|
|
|
}
|
|
|
|
offset += f->GetPosition();
|
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2004-11-03 16:16:57 +00:00
|
|
|
NS_NOTREACHED("No view on any parent? How did that happen?");
|
2003-06-19 23:44:01 +00:00
|
|
|
return nsnull;
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
|
|
|
|
2000-01-12 08:28:24 +00:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
/* virtual */ void
|
|
|
|
nsFrame::ChildIsDirty(nsIFrame* aChild)
|
2000-01-12 08:28:24 +00:00
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
NS_NOTREACHED("should never be called on a frame that doesn't inherit from "
|
|
|
|
"nsContainerFrame");
|
2000-01-12 08:28:24 +00:00
|
|
|
}
|
|
|
|
|
2000-09-12 22:47:09 +00:00
|
|
|
|
2001-08-17 03:13:07 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2001-05-17 23:52:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::GetAccessible(nsIAccessible** aAccessible)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
2001-08-17 03:13:07 +00:00
|
|
|
#endif
|
2001-05-17 23:52:32 +00:00
|
|
|
|
2008-02-20 07:08:55 +00:00
|
|
|
/** Create or retrieve the previously stored overflow area, if the frame does
|
|
|
|
* not overflow and no creation is required return nsnull.
|
|
|
|
* @param aCreateIfNecessary create a new nsRect for the overflow area
|
|
|
|
* @return pointer to the overflow area rectangle
|
|
|
|
*/
|
2003-05-31 10:32:19 +00:00
|
|
|
nsRect*
|
2004-07-16 16:56:21 +00:00
|
|
|
nsIFrame::GetOverflowAreaProperty(PRBool aCreateIfNecessary)
|
2003-05-31 10:32:19 +00:00
|
|
|
{
|
2009-04-06 00:31:50 +00:00
|
|
|
if (!((mOverflow.mType == NS_FRAME_OVERFLOW_LARGE) ||
|
|
|
|
aCreateIfNecessary)) {
|
2003-05-31 10:32:19 +00:00
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPropertyTable *propTable = PresContext()->PropertyTable();
|
2004-08-24 18:50:29 +00:00
|
|
|
void *value = propTable->GetProperty(this,
|
2006-12-26 17:47:52 +00:00
|
|
|
nsGkAtoms::overflowAreaProperty);
|
2004-02-23 21:29:06 +00:00
|
|
|
|
|
|
|
if (value) {
|
|
|
|
return (nsRect*)value; // the property already exists
|
|
|
|
} else if (aCreateIfNecessary) {
|
|
|
|
// The property isn't set yet, so allocate a new rect, set the property,
|
|
|
|
// and return the newly allocated rect
|
|
|
|
nsRect* overflow = new nsRect(0, 0, 0, 0);
|
2006-12-26 17:47:52 +00:00
|
|
|
propTable->SetProperty(this, nsGkAtoms::overflowAreaProperty,
|
2004-08-24 18:50:29 +00:00
|
|
|
overflow, DestroyRectFunc, nsnull);
|
2004-02-23 21:29:06 +00:00
|
|
|
return overflow;
|
2003-05-31 10:32:19 +00:00
|
|
|
}
|
|
|
|
|
2009-04-06 00:31:50 +00:00
|
|
|
NS_NOTREACHED("Frame abuses GetOverflowAreaProperty()");
|
2003-05-31 10:32:19 +00:00
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2009-04-06 00:31:50 +00:00
|
|
|
/** Set the overflowArea rect, storing it as deltas or a separate rect
|
|
|
|
* depending on its size in relation to the primary frame rect.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
nsIFrame::SetOverflowRect(const nsRect& aRect)
|
|
|
|
{
|
|
|
|
PRUint32 l = -aRect.x, // left edge: positive delta is leftwards
|
|
|
|
t = -aRect.y, // top: positive is upwards
|
|
|
|
r = aRect.XMost() - mRect.width, // right: positive is rightwards
|
|
|
|
b = aRect.YMost() - mRect.height; // bottom: positive is downwards
|
|
|
|
if (l <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
|
|
|
t <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
|
|
|
r <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
|
|
|
b <= NS_FRAME_OVERFLOW_DELTA_MAX &&
|
|
|
|
(l | t | r | b) != 0) {
|
|
|
|
// It's a "small" overflow area so we store the deltas for each edge
|
|
|
|
// directly in the frame, rather than allocating a separate rect.
|
|
|
|
// Note that we do NOT store in this way if *all* the deltas are zero,
|
|
|
|
// as that would be indistinguishable from the complete absence of
|
|
|
|
// an overflow rect.
|
|
|
|
DeleteProperty(nsGkAtoms::overflowAreaProperty);
|
|
|
|
mOverflow.mDeltas.mLeft = l;
|
|
|
|
mOverflow.mDeltas.mTop = t;
|
|
|
|
mOverflow.mDeltas.mRight = r;
|
|
|
|
mOverflow.mDeltas.mBottom = b;
|
|
|
|
} else {
|
|
|
|
// it's a large overflow area that we need to store as a property
|
|
|
|
mOverflow.mType = NS_FRAME_OVERFLOW_LARGE;
|
|
|
|
nsRect* overflowArea = GetOverflowAreaProperty(PR_TRUE);
|
|
|
|
NS_ASSERTION(overflowArea, "should have created rect");
|
|
|
|
*overflowArea = aRect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-06 03:55:15 +00:00
|
|
|
inline PRBool
|
|
|
|
IsInlineFrame(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
nsIAtom *type = aFrame->GetType();
|
|
|
|
return type == nsGkAtoms::inlineFrame ||
|
|
|
|
type == nsGkAtoms::positionedInlineFrame;
|
|
|
|
}
|
|
|
|
|
2008-07-08 00:57:47 +00:00
|
|
|
nsRect
|
|
|
|
nsIFrame::GetAdditionalOverflow(const nsRect& aOverflowArea,
|
2008-10-21 07:42:28 +00:00
|
|
|
const nsSize& aNewSize,
|
|
|
|
PRBool* aHasOutlineOrEffects)
|
2008-07-08 00:57:47 +00:00
|
|
|
{
|
2008-09-11 00:24:16 +00:00
|
|
|
nsRect overflowRect =
|
2008-10-21 07:42:28 +00:00
|
|
|
ComputeOutlineAndEffectsRect(this, aHasOutlineOrEffects,
|
2008-09-11 00:24:16 +00:00
|
|
|
aOverflowArea, PR_TRUE);
|
2008-07-08 00:57:47 +00:00
|
|
|
|
|
|
|
// Absolute position clipping
|
|
|
|
PRBool hasAbsPosClip;
|
|
|
|
nsRect absPosClipRect;
|
|
|
|
hasAbsPosClip = GetAbsPosClipRect(GetStyleDisplay(), &absPosClipRect, aNewSize);
|
|
|
|
if (hasAbsPosClip) {
|
|
|
|
overflowRect.IntersectRect(overflowRect, absPosClipRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
return overflowRect;
|
|
|
|
}
|
|
|
|
|
2003-05-31 10:32:19 +00:00
|
|
|
void
|
2004-07-16 16:56:21 +00:00
|
|
|
nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize)
|
|
|
|
{
|
|
|
|
// This is now called FinishAndStoreOverflow() instead of
|
|
|
|
// StoreOverflow() because frame-generic ways of adding overflow
|
2007-01-17 22:31:07 +00:00
|
|
|
// can happen here, e.g. CSS2 outline and native theme.
|
2004-09-01 13:33:17 +00:00
|
|
|
NS_ASSERTION(aNewSize.width == 0 || aNewSize.height == 0 ||
|
|
|
|
aOverflowArea->Contains(nsRect(nsPoint(0, 0), aNewSize)),
|
|
|
|
"Computed overflow area must contain frame bounds");
|
2004-07-16 16:56:21 +00:00
|
|
|
|
2007-01-17 22:31:07 +00:00
|
|
|
const nsStyleDisplay *disp = GetStyleDisplay();
|
2007-09-15 15:14:27 +00:00
|
|
|
if (!IsBoxWrapped() && IsThemed(disp)) {
|
2008-04-01 23:34:20 +00:00
|
|
|
nsRect r(nsPoint(0, 0), aNewSize);
|
2007-03-30 21:11:41 +00:00
|
|
|
nsPresContext *presContext = PresContext();
|
2007-01-17 22:31:07 +00:00
|
|
|
if (presContext->GetTheme()->
|
|
|
|
GetWidgetOverflow(presContext->DeviceContext(), this,
|
|
|
|
disp->mAppearance, &r)) {
|
|
|
|
aOverflowArea->UnionRect(*aOverflowArea, r);
|
|
|
|
}
|
|
|
|
}
|
2008-02-27 09:46:22 +00:00
|
|
|
|
|
|
|
// Overflow area must always include the frame's top-left and bottom-right,
|
|
|
|
// even if the frame rect is empty.
|
2008-04-06 03:55:15 +00:00
|
|
|
// Pending a real fix for bug 426879, don't do this for inline frames
|
|
|
|
// with zero width.
|
|
|
|
if (aNewSize.width != 0 || !IsInlineFrame(this))
|
|
|
|
aOverflowArea->UnionRectIncludeEmpty(*aOverflowArea,
|
|
|
|
nsRect(nsPoint(0, 0), aNewSize));
|
2007-01-17 22:31:07 +00:00
|
|
|
|
2005-04-11 22:03:23 +00:00
|
|
|
PRBool geometricOverflow =
|
|
|
|
aOverflowArea->x < 0 || aOverflowArea->y < 0 ||
|
|
|
|
aOverflowArea->XMost() > aNewSize.width || aOverflowArea->YMost() > aNewSize.height;
|
|
|
|
// Clear geometric overflow area if we clip our children
|
2007-03-27 03:58:17 +00:00
|
|
|
NS_ASSERTION((disp->mOverflowY == NS_STYLE_OVERFLOW_CLIP) ==
|
|
|
|
(disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP),
|
2005-04-11 22:03:23 +00:00
|
|
|
"If one overflow is clip, the other should be too");
|
|
|
|
if (geometricOverflow &&
|
2007-03-27 03:58:17 +00:00
|
|
|
disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP) {
|
2005-04-11 22:03:23 +00:00
|
|
|
*aOverflowArea = nsRect(nsPoint(0, 0), aNewSize);
|
|
|
|
geometricOverflow = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-10-21 07:42:28 +00:00
|
|
|
PRBool hasOutlineOrEffects;
|
|
|
|
*aOverflowArea = GetAdditionalOverflow(*aOverflowArea, aNewSize,
|
|
|
|
&hasOutlineOrEffects);
|
2007-03-27 03:58:17 +00:00
|
|
|
|
2008-09-16 01:51:52 +00:00
|
|
|
/* If we're transformed, transform the overflow rect by the current transformation. */
|
2008-10-01 00:51:05 +00:00
|
|
|
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
2008-09-16 01:51:52 +00:00
|
|
|
GetStyleDisplay()->HasTransform()) {
|
|
|
|
// Save overflow area before the transform
|
|
|
|
SetRectProperty(this, nsGkAtoms::preTransformBBoxProperty, *aOverflowArea);
|
|
|
|
|
|
|
|
/* Since our size might not actually have been computed yet, we need to make sure that we use the
|
|
|
|
* correct dimensions by overriding the stored bounding rectangle with the value the caller has
|
|
|
|
* ensured us we'll use.
|
|
|
|
*/
|
|
|
|
nsRect newBounds(nsPoint(0, 0), aNewSize);
|
|
|
|
*aOverflowArea = nsDisplayTransform::TransformRect(*aOverflowArea, this, nsPoint(0, 0), &newBounds);
|
|
|
|
}
|
2008-10-21 07:42:28 +00:00
|
|
|
|
|
|
|
PRBool overflowChanged;
|
2008-09-16 01:51:52 +00:00
|
|
|
if (*aOverflowArea != nsRect(nsPoint(0, 0), aNewSize)) {
|
2009-04-06 00:31:50 +00:00
|
|
|
overflowChanged = *aOverflowArea != GetOverflowRect();
|
|
|
|
SetOverflowRect(*aOverflowArea);
|
2008-09-16 01:51:52 +00:00
|
|
|
}
|
2003-05-31 10:32:19 +00:00
|
|
|
else {
|
2009-04-06 00:31:50 +00:00
|
|
|
if (HasOverflowRect()) {
|
2003-05-31 10:32:19 +00:00
|
|
|
// remove the previously stored overflow area
|
2009-04-06 00:31:50 +00:00
|
|
|
ClearOverflowRect();
|
2008-10-21 07:42:28 +00:00
|
|
|
overflowChanged = PR_TRUE;
|
|
|
|
} else {
|
|
|
|
overflowChanged = PR_FALSE;
|
2003-05-31 10:32:19 +00:00
|
|
|
}
|
2008-10-21 07:42:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (overflowChanged && hasOutlineOrEffects) {
|
|
|
|
// When there's an outline or box-shadow or SVG effects, changes to
|
|
|
|
// those styles might require repainting of the old and new overflow
|
|
|
|
// areas. Repainting of the old overflow area is handled in
|
|
|
|
// nsCSSFrameConstructor::DoApplyRenderingChangeToTree in response
|
|
|
|
// to nsChangeHint_RepaintFrame. Since the new overflow area is not
|
|
|
|
// known at that time, we have to handle it here.
|
|
|
|
// If the overflow area hasn't changed, then we don't have to do
|
|
|
|
// anything here since repainting the old overflow area was enough.
|
|
|
|
// If there is no outline or other effects now, then we don't have
|
|
|
|
// to do anything here since removing those styles can't require
|
|
|
|
// repainting of areas that weren't in the old overflow area.
|
|
|
|
Invalidate(*aOverflowArea);
|
2008-09-16 01:51:52 +00:00
|
|
|
}
|
2003-05-31 10:32:19 +00:00
|
|
|
}
|
|
|
|
|
2003-09-13 16:21:41 +00:00
|
|
|
void
|
2004-12-27 15:05:18 +00:00
|
|
|
nsFrame::ConsiderChildOverflow(nsRect& aOverflowArea,
|
|
|
|
nsIFrame* aChildFrame)
|
2003-09-13 16:21:41 +00:00
|
|
|
{
|
2004-04-14 06:28:25 +00:00
|
|
|
const nsStyleDisplay* disp = GetStyleDisplay();
|
2004-08-10 01:32:10 +00:00
|
|
|
// check here also for hidden as table frames (table, tr and td) currently
|
2004-04-14 06:28:25 +00:00
|
|
|
// don't wrap their content into a scrollable frame if overflow is specified
|
2004-09-02 23:27:23 +00:00
|
|
|
if (!disp->IsTableClip()) {
|
2008-02-20 07:08:55 +00:00
|
|
|
nsRect childOverflow = aChildFrame->GetOverflowRect();
|
|
|
|
childOverflow.MoveBy(aChildFrame->GetPosition());
|
|
|
|
aOverflowArea.UnionRect(aOverflowArea, childOverflow);
|
2003-09-13 16:21:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-15 00:55:00 +00:00
|
|
|
NS_IMETHODIMP
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::GetParentStyleContextFrame(nsPresContext* aPresContext,
|
2003-06-15 00:55:00 +00:00
|
|
|
nsIFrame** aProviderFrame,
|
|
|
|
PRBool* aIsChild)
|
|
|
|
{
|
|
|
|
return DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function takes a "special" frame and _if_ that frame is the
|
|
|
|
* anonymous block crated by an ib split it returns the split inline
|
|
|
|
* as aSpecialSibling. This is needed because the split inline's
|
2003-06-25 22:55:27 +00:00
|
|
|
* style context is the parent of the anonymous block's srtyle context.
|
2003-06-15 00:55:00 +00:00
|
|
|
*
|
2008-09-11 00:24:16 +00:00
|
|
|
* If aFrame is not the anonymous block, aSpecialSibling is set to null.
|
2003-06-15 00:55:00 +00:00
|
|
|
*/
|
|
|
|
static nsresult
|
2008-09-11 00:24:16 +00:00
|
|
|
GetIBSpecialSiblingForAnonymousBlock(nsPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIFrame** aSpecialSibling)
|
2003-06-15 00:55:00 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aFrame, "Must have a non-null frame!");
|
2003-06-28 11:48:14 +00:00
|
|
|
NS_ASSERTION(aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL,
|
2003-06-15 00:55:00 +00:00
|
|
|
"GetIBSpecialSibling should not be called on a non-special frame");
|
2008-09-11 00:24:16 +00:00
|
|
|
|
|
|
|
nsIAtom* type = aFrame->GetStyleContext()->GetPseudoType();
|
|
|
|
if (type != nsCSSAnonBoxes::mozAnonymousBlock &&
|
|
|
|
type != nsCSSAnonBoxes::mozAnonymousPositionedBlock) {
|
|
|
|
// it's not the anonymous block
|
|
|
|
*aSpecialSibling = nsnull;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2003-06-15 00:55:00 +00:00
|
|
|
// Find the first-in-flow of the frame. (Ugh. This ends up
|
|
|
|
// being O(N^2) when it is called O(N) times.)
|
|
|
|
aFrame = aFrame->GetFirstInFlow();
|
|
|
|
|
|
|
|
/*
|
2006-12-26 17:47:52 +00:00
|
|
|
* Now look up the nsGkAtoms::IBSplitSpecialPrevSibling
|
2003-06-15 00:55:00 +00:00
|
|
|
* property, which is only set on the anonymous block frames we're
|
|
|
|
* interested in.
|
|
|
|
*/
|
2004-02-23 21:29:06 +00:00
|
|
|
nsresult rv;
|
2007-07-08 07:08:04 +00:00
|
|
|
nsIFrame *specialSibling = static_cast<nsIFrame*>
|
|
|
|
(aPresContext->PropertyTable()->GetProperty(aFrame,
|
2006-12-26 17:47:52 +00:00
|
|
|
nsGkAtoms::IBSplitSpecialPrevSibling, &rv));
|
2004-02-23 21:29:06 +00:00
|
|
|
|
2007-04-15 23:14:26 +00:00
|
|
|
if (NS_PROPTABLE_PROP_NOT_THERE == rv) {
|
|
|
|
*aSpecialSibling = nsnull;
|
|
|
|
rv = NS_OK;
|
|
|
|
} else if (NS_SUCCEEDED(rv)) {
|
2003-06-15 00:55:00 +00:00
|
|
|
NS_ASSERTION(specialSibling, "null special sibling");
|
|
|
|
*aSpecialSibling = specialSibling;
|
|
|
|
}
|
|
|
|
|
2007-04-15 23:14:26 +00:00
|
|
|
return rv;
|
2005-12-17 18:58:47 +00:00
|
|
|
}
|
|
|
|
|
2003-06-15 00:55:00 +00:00
|
|
|
/**
|
|
|
|
* Get the parent, corrected for the mangled frame tree resulting from
|
|
|
|
* having a block within an inline. The result only differs from the
|
|
|
|
* result of |GetParent| when |GetParent| returns an anonymous block
|
|
|
|
* that was created for an element that was 'display: inline' because
|
|
|
|
* that element contained a block.
|
|
|
|
*
|
2003-10-11 12:00:05 +00:00
|
|
|
* Also skip anonymous scrolled-content parents; inherit directly from the
|
|
|
|
* outer scroll frame.
|
2003-06-15 00:55:00 +00:00
|
|
|
*/
|
|
|
|
static nsresult
|
2004-07-31 23:15:21 +00:00
|
|
|
GetCorrectedParent(nsPresContext* aPresContext, nsIFrame* aFrame,
|
2003-06-15 00:55:00 +00:00
|
|
|
nsIFrame** aSpecialParent)
|
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame *parent = aFrame->GetParent();
|
2007-04-15 23:14:26 +00:00
|
|
|
if (!parent) {
|
|
|
|
*aSpecialParent = nsnull;
|
|
|
|
} else {
|
2007-04-16 05:55:42 +00:00
|
|
|
nsIAtom* pseudo = aFrame->GetStyleContext()->GetPseudoType();
|
|
|
|
// Outer tables are always anon boxes; if we're in here for an outer
|
|
|
|
// table, that actually means its the _inner_ table that wants to
|
|
|
|
// know its parent. So get the pseudo of the inner in that case.
|
|
|
|
if (pseudo == nsCSSAnonBoxes::tableOuter) {
|
|
|
|
pseudo =
|
|
|
|
aFrame->GetFirstChild(nsnull)->GetStyleContext()->GetPseudoType();
|
|
|
|
}
|
|
|
|
*aSpecialParent = nsFrame::CorrectStyleParentFrame(parent, pseudo);
|
2007-04-15 23:14:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsIFrame*
|
|
|
|
nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
|
|
|
|
nsIAtom* aChildPseudo)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aProspectiveParent, "Must have a prospective parent");
|
|
|
|
|
|
|
|
// Anon boxes are parented to their actual parent already, except
|
|
|
|
// for non-elements. Those should not be treated as an anon box.
|
|
|
|
if (aChildPseudo && aChildPseudo != nsCSSAnonBoxes::mozNonElement &&
|
|
|
|
nsCSSAnonBoxes::IsAnonBox(aChildPseudo)) {
|
|
|
|
NS_ASSERTION(aChildPseudo != nsCSSAnonBoxes::mozAnonymousBlock &&
|
|
|
|
aChildPseudo != nsCSSAnonBoxes::mozAnonymousPositionedBlock,
|
|
|
|
"Should have dealt with kids that have NS_FRAME_IS_SPECIAL "
|
|
|
|
"elsewhere");
|
|
|
|
return aProspectiveParent;
|
|
|
|
}
|
|
|
|
|
2007-10-19 17:41:29 +00:00
|
|
|
// Otherwise, walk up out of all anon boxes. For placeholder frames, walk out
|
|
|
|
// of all pseudo-elements as well. Otherwise ReParentStyleContext could cause
|
2007-07-18 02:01:32 +00:00
|
|
|
// style data to be out of sync with the frame tree.
|
2007-04-15 23:14:26 +00:00
|
|
|
nsIFrame* parent = aProspectiveParent;
|
|
|
|
do {
|
|
|
|
if (parent->GetStateBits() & NS_FRAME_IS_SPECIAL) {
|
|
|
|
nsIFrame* sibling;
|
|
|
|
nsresult rv =
|
2008-09-11 00:24:16 +00:00
|
|
|
GetIBSpecialSiblingForAnonymousBlock(parent->PresContext(), parent, &sibling);
|
2007-04-15 23:14:26 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
2008-09-11 00:24:16 +00:00
|
|
|
// If GetIBSpecialSiblingForAnonymousBlock fails, then what?
|
|
|
|
// we used to return what is now |aProspectiveParent|, but maybe
|
|
|
|
// |parent| would make more sense?
|
2007-04-15 23:14:26 +00:00
|
|
|
NS_NOTREACHED("Shouldn't get here");
|
|
|
|
return aProspectiveParent;
|
2005-12-17 18:58:47 +00:00
|
|
|
}
|
|
|
|
|
2007-04-15 23:14:26 +00:00
|
|
|
if (sibling) {
|
|
|
|
// |parent| was the block in an {ib} split; use the inline as
|
|
|
|
// |the style parent.
|
|
|
|
parent = sibling;
|
2003-10-11 12:00:05 +00:00
|
|
|
}
|
2003-06-15 00:55:00 +00:00
|
|
|
}
|
2007-04-15 23:14:26 +00:00
|
|
|
|
|
|
|
nsIAtom* parentPseudo = parent->GetStyleContext()->GetPseudoType();
|
2007-07-18 02:01:32 +00:00
|
|
|
if (!parentPseudo ||
|
|
|
|
(!nsCSSAnonBoxes::IsAnonBox(parentPseudo) &&
|
|
|
|
// nsPlaceholderFrame pases in nsGkAtoms::placeholderFrame for
|
|
|
|
// aChildPseudo (even though that's not a valid pseudo-type) just to
|
|
|
|
// trigger this behavior of walking up to the nearest non-pseudo
|
|
|
|
// ancestor.
|
|
|
|
aChildPseudo != nsGkAtoms::placeholderFrame)) {
|
2007-04-15 23:14:26 +00:00
|
|
|
return parent;
|
2003-06-15 00:55:00 +00:00
|
|
|
}
|
|
|
|
|
2007-04-15 23:14:26 +00:00
|
|
|
parent = parent->GetParent();
|
|
|
|
} while (parent);
|
|
|
|
|
2008-09-08 08:13:17 +00:00
|
|
|
if (aProspectiveParent->GetStyleContext()->GetPseudoType() ==
|
|
|
|
nsCSSAnonBoxes::viewportScroll) {
|
|
|
|
// aProspectiveParent is the scrollframe for a viewport
|
|
|
|
// and the kids are the anonymous scrollbars
|
|
|
|
return aProspectiveParent;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can get here if the root element is absolutely positioned.
|
|
|
|
// We can't test for this very accurately, but it can only happen
|
|
|
|
// when the prospective parent is a canvas frame.
|
|
|
|
NS_ASSERTION(aProspectiveParent->GetType() == nsGkAtoms::canvasFrame,
|
2007-04-15 23:14:26 +00:00
|
|
|
"Should have found a parent before this");
|
2008-09-08 08:13:17 +00:00
|
|
|
return nsnull;
|
2003-06-15 00:55:00 +00:00
|
|
|
}
|
|
|
|
|
2002-03-27 02:38:13 +00:00
|
|
|
nsresult
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::DoGetParentStyleContextFrame(nsPresContext* aPresContext,
|
2002-03-27 02:38:13 +00:00
|
|
|
nsIFrame** aProviderFrame,
|
|
|
|
PRBool* aIsChild)
|
|
|
|
{
|
|
|
|
*aIsChild = PR_FALSE;
|
2002-09-12 20:33:11 +00:00
|
|
|
*aProviderFrame = nsnull;
|
2006-08-12 02:14:39 +00:00
|
|
|
if (mContent && !mContent->GetParent() &&
|
|
|
|
!GetStyleContext()->GetPseudoType()) {
|
2004-03-29 16:00:38 +00:00
|
|
|
// we're a frame for the root. We have no style context parent.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-03-27 02:38:13 +00:00
|
|
|
if (!(mState & NS_FRAME_OUT_OF_FLOW)) {
|
2002-09-12 20:33:11 +00:00
|
|
|
/*
|
|
|
|
* If this frame is the anonymous block created when an inline
|
|
|
|
* with a block inside it got split, then the parent style context
|
|
|
|
* is on the first of the three special frames. We can get to it
|
2008-09-11 00:24:16 +00:00
|
|
|
* using GetIBSpecialSiblingForAnonymousBlock
|
2002-09-12 20:33:11 +00:00
|
|
|
*/
|
|
|
|
if (mState & NS_FRAME_IS_SPECIAL) {
|
2008-09-11 00:24:16 +00:00
|
|
|
nsresult rv =
|
|
|
|
GetIBSpecialSiblingForAnonymousBlock(aPresContext, this, aProviderFrame);
|
2007-04-15 23:14:26 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_NOTREACHED("Shouldn't get here");
|
|
|
|
*aProviderFrame = nsnull;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*aProviderFrame) {
|
2002-09-12 20:33:11 +00:00
|
|
|
return NS_OK;
|
2007-04-15 23:14:26 +00:00
|
|
|
}
|
2002-09-12 20:33:11 +00:00
|
|
|
}
|
|
|
|
|
2002-03-27 02:38:13 +00:00
|
|
|
// If this frame is one of the blocks that split an inline, we must
|
|
|
|
// return the "special" inline parent, i.e., the parent that this
|
|
|
|
// frame would have if we didn't mangle the frame structure.
|
2003-06-15 00:55:00 +00:00
|
|
|
return GetCorrectedParent(aPresContext, this, aProviderFrame);
|
2002-03-27 02:38:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// For out-of-flow frames, we must resolve underneath the
|
|
|
|
// placeholder's parent.
|
2007-10-02 05:57:45 +00:00
|
|
|
nsIFrame* oofFrame = this;
|
2009-08-31 18:25:36 +00:00
|
|
|
if ((oofFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
|
|
|
|
GetPrevInFlow()) {
|
|
|
|
// Out of flows that are continuations do not
|
2007-10-02 05:57:45 +00:00
|
|
|
// have placeholders. Use their first-in-flow's placeholder.
|
|
|
|
oofFrame = oofFrame->GetFirstInFlow();
|
|
|
|
}
|
2004-02-23 21:29:06 +00:00
|
|
|
nsIFrame *placeholder =
|
2007-10-02 05:57:45 +00:00
|
|
|
aPresContext->FrameManager()->GetPlaceholderFrameFor(oofFrame);
|
2002-03-27 02:38:13 +00:00
|
|
|
if (!placeholder) {
|
|
|
|
NS_NOTREACHED("no placeholder frame for out-of-flow frame");
|
2003-06-15 00:55:00 +00:00
|
|
|
GetCorrectedParent(aPresContext, this, aProviderFrame);
|
2002-03-27 02:38:13 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2007-07-08 07:08:04 +00:00
|
|
|
return static_cast<nsFrame*>(placeholder)->
|
2003-06-15 00:55:00 +00:00
|
|
|
GetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
|
2000-09-12 22:47:09 +00:00
|
|
|
}
|
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
//-----------------------------------------------------------------------------------
|
|
|
|
|
1998-08-03 22:22:27 +00:00
|
|
|
|
1998-05-08 18:33:42 +00:00
|
|
|
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
void
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
|
1999-07-15 18:19:03 +00:00
|
|
|
{
|
|
|
|
if (!aFrame || !*aFrame)
|
|
|
|
return;
|
|
|
|
nsIFrame *child = *aFrame;
|
2001-05-11 08:04:29 +00:00
|
|
|
//if we are a block frame then go for the last line of 'this'
|
1999-07-15 18:19:03 +00:00
|
|
|
while (1){
|
2004-01-09 14:20:53 +00:00
|
|
|
child = child->GetFirstChild(nsnull);
|
|
|
|
if (!child)
|
1999-07-15 18:19:03 +00:00
|
|
|
return;//nothing to do
|
2005-01-26 06:46:35 +00:00
|
|
|
nsIFrame* siblingFrame;
|
|
|
|
nsIContent* content;
|
|
|
|
//ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
|
|
|
|
//see bug 278197 comment #12 #13 for details
|
|
|
|
while ((siblingFrame = child->GetNextSibling()) &&
|
|
|
|
(content = siblingFrame->GetContent()) &&
|
2008-07-23 04:50:20 +00:00
|
|
|
!content->IsRootOfNativeAnonymousSubtree())
|
2005-01-26 06:46:35 +00:00
|
|
|
child = siblingFrame;
|
1999-07-15 18:19:03 +00:00
|
|
|
*aFrame = child;
|
|
|
|
}
|
|
|
|
}
|
1998-05-08 18:33:42 +00:00
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
void
|
2004-07-31 23:15:21 +00:00
|
|
|
nsFrame::GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
|
1999-10-22 00:19:18 +00:00
|
|
|
{
|
|
|
|
if (!aFrame || !*aFrame)
|
|
|
|
return;
|
|
|
|
nsIFrame *child = *aFrame;
|
|
|
|
while (1){
|
2004-01-09 14:20:53 +00:00
|
|
|
child = child->GetFirstChild(nsnull);
|
|
|
|
if (!child)
|
1999-10-22 00:19:18 +00:00
|
|
|
return;//nothing to do
|
|
|
|
*aFrame = child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-01 06:20:16 +00:00
|
|
|
nsresult
|
2004-08-24 18:50:29 +00:00
|
|
|
nsIFrame::SetProperty(nsIAtom* aPropName,
|
|
|
|
void* aPropValue,
|
|
|
|
NSPropertyDtorFunc aPropDtorFunc,
|
|
|
|
void* aDtorData)
|
2002-12-04 00:58:52 +00:00
|
|
|
{
|
2007-03-30 21:11:41 +00:00
|
|
|
return PresContext()->PropertyTable()->
|
2004-08-24 18:50:29 +00:00
|
|
|
SetProperty(this, aPropName, aPropValue, aPropDtorFunc, aDtorData);
|
2002-12-04 00:58:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void*
|
2004-06-01 06:20:16 +00:00
|
|
|
nsIFrame::GetProperty(nsIAtom* aPropName, nsresult* aStatus) const
|
2002-12-04 00:58:52 +00:00
|
|
|
{
|
2007-03-30 21:11:41 +00:00
|
|
|
return PresContext()->PropertyTable()->GetProperty(this, aPropName,
|
2004-08-24 18:50:29 +00:00
|
|
|
aStatus);
|
2002-12-04 00:58:52 +00:00
|
|
|
}
|
|
|
|
|
2004-06-01 06:20:16 +00:00
|
|
|
/* virtual */ void*
|
|
|
|
nsIFrame::GetPropertyExternal(nsIAtom* aPropName, nsresult* aStatus) const
|
2003-01-09 06:49:07 +00:00
|
|
|
{
|
2004-06-01 06:20:16 +00:00
|
|
|
return GetProperty(aPropName, aStatus);
|
2003-01-09 06:49:07 +00:00
|
|
|
}
|
|
|
|
|
2004-08-24 18:50:29 +00:00
|
|
|
nsresult
|
|
|
|
nsIFrame::DeleteProperty(nsIAtom* aPropName) const
|
|
|
|
{
|
2007-03-30 21:11:41 +00:00
|
|
|
return PresContext()->PropertyTable()->DeleteProperty(this, aPropName);
|
2004-08-24 18:50:29 +00:00
|
|
|
}
|
|
|
|
|
2004-06-01 06:20:16 +00:00
|
|
|
void*
|
2004-08-24 18:50:29 +00:00
|
|
|
nsIFrame::UnsetProperty(nsIAtom* aPropName, nsresult* aStatus) const
|
2001-03-09 03:29:00 +00:00
|
|
|
{
|
2007-03-30 21:11:41 +00:00
|
|
|
return PresContext()->PropertyTable()->UnsetProperty(this, aPropName,
|
2004-08-24 18:50:29 +00:00
|
|
|
aStatus);
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
|
|
|
|
2008-01-10 20:56:49 +00:00
|
|
|
/* virtual */ const void*
|
2004-06-01 06:20:16 +00:00
|
|
|
nsFrame::GetStyleDataExternal(nsStyleStructID aSID) const
|
2001-03-09 03:29:00 +00:00
|
|
|
{
|
2004-06-01 06:20:16 +00:00
|
|
|
NS_ASSERTION(mStyleContext, "unexpected null pointer");
|
|
|
|
return mStyleContext->GetStyleData(aSID);
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
|
|
|
|
2005-03-31 01:38:04 +00:00
|
|
|
/* virtual */ PRBool
|
2004-10-19 02:24:27 +00:00
|
|
|
nsIFrame::IsFocusable(PRInt32 *aTabIndex, PRBool aWithMouse)
|
2004-07-24 21:12:43 +00:00
|
|
|
{
|
|
|
|
PRInt32 tabIndex = -1;
|
2005-07-21 19:27:18 +00:00
|
|
|
if (aTabIndex) {
|
|
|
|
*aTabIndex = -1; // Default for early return is not focusable
|
|
|
|
}
|
2004-07-24 21:12:43 +00:00
|
|
|
PRBool isFocusable = PR_FALSE;
|
|
|
|
|
2006-05-05 06:52:21 +00:00
|
|
|
if (mContent && mContent->IsNodeOfType(nsINode::eELEMENT) &&
|
2004-07-29 18:06:55 +00:00
|
|
|
AreAncestorViewsVisible()) {
|
2004-07-24 21:12:43 +00:00
|
|
|
const nsStyleVisibility* vis = GetStyleVisibility();
|
|
|
|
if (vis->mVisible != NS_STYLE_VISIBILITY_COLLAPSE &&
|
|
|
|
vis->mVisible != NS_STYLE_VISIBILITY_HIDDEN) {
|
|
|
|
const nsStyleUserInterface* ui = GetStyleUserInterface();
|
|
|
|
if (ui->mUserFocus != NS_STYLE_USER_FOCUS_IGNORE &&
|
|
|
|
ui->mUserFocus != NS_STYLE_USER_FOCUS_NONE) {
|
|
|
|
// Pass in default tabindex of -1 for nonfocusable and 0 for focusable
|
|
|
|
tabIndex = 0;
|
|
|
|
}
|
|
|
|
isFocusable = mContent->IsFocusable(&tabIndex);
|
2004-10-19 02:24:27 +00:00
|
|
|
if (!isFocusable && !aWithMouse &&
|
2006-12-26 17:47:52 +00:00
|
|
|
GetType() == nsGkAtoms::scrollFrame &&
|
2009-08-25 00:51:57 +00:00
|
|
|
mContent->IsNodeOfType(nsINode::eHTML) &&
|
2008-07-23 04:50:20 +00:00
|
|
|
!mContent->IsRootOfNativeAnonymousSubtree() &&
|
|
|
|
mContent->GetParent() &&
|
2006-12-26 17:47:52 +00:00
|
|
|
!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
|
2004-10-19 02:24:27 +00:00
|
|
|
// Elements with scrollable view are focusable with script & tabbable
|
2004-09-01 14:58:34 +00:00
|
|
|
// Otherwise you couldn't scroll them with keyboard, which is
|
|
|
|
// an accessibility issue (e.g. Section 508 rules)
|
2004-10-19 02:24:27 +00:00
|
|
|
// However, we don't make them to be focusable with the mouse,
|
|
|
|
// because the extra focus outlines are considered unnecessarily ugly.
|
|
|
|
// When clicked on, the selection position within the element
|
|
|
|
// will be enough to make them keyboard scrollable.
|
2009-01-12 19:20:59 +00:00
|
|
|
nsIScrollableFrame *scrollFrame = do_QueryFrame(this);
|
2004-09-01 14:58:34 +00:00
|
|
|
if (scrollFrame) {
|
2007-09-04 12:14:52 +00:00
|
|
|
nsMargin margin = scrollFrame->GetActualScrollbarSizes();
|
|
|
|
if (margin.top || margin.right || margin.bottom || margin.left) {
|
2004-09-01 14:58:34 +00:00
|
|
|
// Scroll bars will be used for overflow
|
|
|
|
isFocusable = PR_TRUE;
|
|
|
|
tabIndex = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-07-24 21:12:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aTabIndex) {
|
|
|
|
*aTabIndex = tabIndex;
|
|
|
|
}
|
|
|
|
return isFocusable;
|
|
|
|
}
|
|
|
|
|
2005-12-06 00:32:52 +00:00
|
|
|
/**
|
|
|
|
* @return PR_TRUE if this text frame ends with a newline character. It
|
|
|
|
* should return PR_FALSE if this is not a text frame.
|
|
|
|
*/
|
|
|
|
PRBool
|
|
|
|
nsIFrame::HasTerminalNewline() const
|
|
|
|
{
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2004-12-30 21:56:11 +00:00
|
|
|
/* static */
|
|
|
|
void nsFrame::FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
|
|
|
|
nsIFrame::Cursor& aCursor)
|
|
|
|
{
|
|
|
|
aCursor.mCursor = ui->mCursor;
|
2005-07-01 04:29:42 +00:00
|
|
|
aCursor.mHaveHotspot = PR_FALSE;
|
|
|
|
aCursor.mHotspotX = aCursor.mHotspotY = 0.0f;
|
2004-12-30 21:56:11 +00:00
|
|
|
|
2005-07-01 04:29:42 +00:00
|
|
|
for (nsCursorImage *item = ui->mCursorArray,
|
|
|
|
*item_end = ui->mCursorArray + ui->mCursorArrayLength;
|
|
|
|
item < item_end; ++item) {
|
2004-12-30 21:56:11 +00:00
|
|
|
PRUint32 status;
|
2005-07-01 04:29:42 +00:00
|
|
|
nsresult rv = item->mImage->GetImageStatus(&status);
|
2009-09-12 22:44:18 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_LOAD_COMPLETE)) {
|
2004-12-30 21:56:11 +00:00
|
|
|
// This is the one we want
|
2005-07-01 04:29:42 +00:00
|
|
|
item->mImage->GetImage(getter_AddRefs(aCursor.mContainer));
|
|
|
|
aCursor.mHaveHotspot = item->mHaveHotspot;
|
|
|
|
aCursor.mHotspotX = item->mHotspotX;
|
|
|
|
aCursor.mHotspotY = item->mHotspotY;
|
2004-12-30 21:56:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-28 18:37:50 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::RefreshSizeCache(nsBoxLayoutState& aState)
|
|
|
|
{
|
2007-04-01 15:15:17 +00:00
|
|
|
// XXXbz this comment needs some rewriting to make sense in the
|
|
|
|
// post-reflow-branch world.
|
|
|
|
|
2004-09-28 18:37:50 +00:00
|
|
|
// Ok we need to compute our minimum, preferred, and maximum sizes.
|
|
|
|
// 1) Maximum size. This is easy. Its infinite unless it is overloaded by CSS.
|
|
|
|
// 2) Preferred size. This is a little harder. This is the size the block would be
|
|
|
|
// if it were laid out on an infinite canvas. So we can get this by reflowing
|
|
|
|
// the block with and INTRINSIC width and height. We can also do a nice optimization
|
|
|
|
// for incremental reflow. If the reflow is incremental then we can pass a flag to
|
|
|
|
// have the block compute the preferred width for us! Preferred height can just be
|
|
|
|
// the minimum height;
|
|
|
|
// 3) Minimum size. This is a toughy. We can pass the block a flag asking for the max element
|
|
|
|
// size. That would give us the width. Unfortunately you can only ask for a maxElementSize
|
|
|
|
// during an incremental reflow. So on other reflows we will just have to use 0.
|
|
|
|
// The min height on the other hand is fairly easy we need to get the largest
|
|
|
|
// line height. This can be done with the line iterator.
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
// if we do have a rendering context
|
2004-09-28 18:37:50 +00:00
|
|
|
nsresult rv = NS_OK;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsIRenderingContext* rendContext = aState.GetRenderingContext();
|
|
|
|
if (rendContext) {
|
2004-09-28 18:37:50 +00:00
|
|
|
nsPresContext* presContext = aState.PresContext();
|
|
|
|
|
2005-11-20 22:05:24 +00:00
|
|
|
// If we don't have any HTML constraints and it's a resize, then nothing in the block
|
2004-09-28 18:37:50 +00:00
|
|
|
// could have changed, so no refresh is necessary.
|
|
|
|
nsBoxLayoutMetrics* metrics = BoxMetrics();
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (!DoesNeedRecalc(metrics->mBlockPrefSize))
|
2005-04-28 21:57:22 +00:00
|
|
|
return NS_OK;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
// get the old rect.
|
|
|
|
nsRect oldRect = GetRect();
|
|
|
|
|
|
|
|
// the rect we plan to size to.
|
|
|
|
nsRect rect(oldRect);
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsMargin bp(0,0,0,0);
|
|
|
|
GetBorderAndPadding(bp);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
metrics->mBlockPrefSize.width = GetPrefWidth(rendContext) + bp.LeftRight();
|
|
|
|
metrics->mBlockMinSize.width = GetMinWidth(rendContext) + bp.LeftRight();
|
2005-12-15 23:08:07 +00:00
|
|
|
|
2004-09-28 18:37:50 +00:00
|
|
|
// do the nasty.
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsHTMLReflowMetrics desiredSize;
|
|
|
|
rv = BoxReflow(aState, presContext, desiredSize, rendContext,
|
|
|
|
rect.x, rect.y,
|
|
|
|
metrics->mBlockPrefSize.width, NS_UNCONSTRAINEDSIZE);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
nsRect newRect = GetRect();
|
|
|
|
|
|
|
|
// make sure we draw any size change
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (oldRect.width != newRect.width || oldRect.height != newRect.height) {
|
|
|
|
newRect.x = 0;
|
|
|
|
newRect.y = 0;
|
|
|
|
Redraw(aState, &newRect);
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2008-03-13 09:14:16 +00:00
|
|
|
metrics->mBlockMinSize.height = 0;
|
|
|
|
// ok we need the max ascent of the items on the line. So to do this
|
|
|
|
// ask the block for its line iterator. Get the max ascent.
|
2008-10-30 19:17:59 +00:00
|
|
|
nsAutoLineIterator lines = GetLineIterator();
|
2008-03-13 09:14:16 +00:00
|
|
|
if (lines)
|
|
|
|
{
|
|
|
|
metrics->mBlockMinSize.height = 0;
|
|
|
|
int count = 0;
|
|
|
|
nsIFrame* firstFrame = nsnull;
|
|
|
|
PRInt32 framesOnLine;
|
|
|
|
nsRect lineBounds;
|
|
|
|
PRUint32 lineFlags;
|
|
|
|
|
|
|
|
do {
|
|
|
|
lines->GetLine(count, &firstFrame, &framesOnLine, lineBounds, &lineFlags);
|
|
|
|
|
|
|
|
if (lineBounds.height > metrics->mBlockMinSize.height)
|
|
|
|
metrics->mBlockMinSize.height = lineBounds.height;
|
|
|
|
|
|
|
|
count++;
|
|
|
|
} while(firstFrame);
|
|
|
|
} else {
|
|
|
|
metrics->mBlockMinSize.height = desiredSize.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
metrics->mBlockPrefSize.height = metrics->mBlockMinSize.height;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
2007-01-23 04:06:56 +00:00
|
|
|
if (desiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
|
|
|
|
if (!nsLayoutUtils::GetFirstLineBaseline(this, &metrics->mBlockAscent))
|
|
|
|
metrics->mBlockAscent = GetBaseline();
|
|
|
|
} else {
|
|
|
|
metrics->mBlockAscent = desiredSize.ascent;
|
|
|
|
}
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_adaptor
|
|
|
|
printf("min=(%d,%d), pref=(%d,%d), ascent=%d\n", metrics->mBlockMinSize.width,
|
|
|
|
metrics->mBlockMinSize.height,
|
|
|
|
metrics->mBlockPrefSize.width,
|
|
|
|
metrics->mBlockPrefSize.height,
|
|
|
|
metrics->mBlockAscent);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2008-10-30 19:17:59 +00:00
|
|
|
/* virtual */ nsILineIterator*
|
|
|
|
nsFrame::GetLineIterator()
|
|
|
|
{
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
nsSize
|
|
|
|
nsFrame::GetPrefSize(nsBoxLayoutState& aState)
|
2004-09-28 18:37:50 +00:00
|
|
|
{
|
2007-01-08 02:57:59 +00:00
|
|
|
nsSize size(0,0);
|
|
|
|
DISPLAY_PREF_SIZE(this, size);
|
2004-09-28 18:37:50 +00:00
|
|
|
// If the size is cached, and there are no HTML constraints that we might
|
|
|
|
// be depending on, then we just return the cached size.
|
|
|
|
nsBoxLayoutMetrics *metrics = BoxMetrics();
|
2005-04-28 21:57:22 +00:00
|
|
|
if (!DoesNeedRecalc(metrics->mPrefSize)) {
|
2007-01-08 02:57:59 +00:00
|
|
|
size = metrics->mPrefSize;
|
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
if (IsCollapsed(aState))
|
2007-01-08 02:57:59 +00:00
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
// get our size in CSS.
|
|
|
|
PRBool completelyRedefined = nsIBox::AddCSSPrefSize(aState, this, size);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
// Refresh our caches with new sizes.
|
|
|
|
if (!completelyRedefined) {
|
|
|
|
RefreshSizeCache(aState);
|
|
|
|
size = metrics->mBlockPrefSize;
|
|
|
|
|
|
|
|
// notice we don't need to add our borders or padding
|
|
|
|
// in. That's because the block did it for us.
|
|
|
|
nsIBox::AddCSSPrefSize(aState, this, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
metrics->mPrefSize = size;
|
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
nsSize
|
|
|
|
nsFrame::GetMinSize(nsBoxLayoutState& aState)
|
2004-09-28 18:37:50 +00:00
|
|
|
{
|
2007-01-08 02:57:59 +00:00
|
|
|
nsSize size(0,0);
|
|
|
|
DISPLAY_MIN_SIZE(this, size);
|
2004-09-28 18:37:50 +00:00
|
|
|
// Don't use the cache if we have HTMLReflowState constraints --- they might have changed
|
|
|
|
nsBoxLayoutMetrics *metrics = BoxMetrics();
|
2005-04-28 21:57:22 +00:00
|
|
|
if (!DoesNeedRecalc(metrics->mMinSize)) {
|
2007-01-08 02:57:59 +00:00
|
|
|
size = metrics->mMinSize;
|
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
if (IsCollapsed(aState))
|
2007-01-08 02:57:59 +00:00
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
// get our size in CSS.
|
|
|
|
PRBool completelyRedefined = nsIBox::AddCSSMinSize(aState, this, size);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
// Refresh our caches with new sizes.
|
|
|
|
if (!completelyRedefined) {
|
|
|
|
RefreshSizeCache(aState);
|
|
|
|
size = metrics->mBlockMinSize;
|
|
|
|
nsIBox::AddCSSMinSize(aState, this, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
metrics->mMinSize = size;
|
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
nsSize
|
|
|
|
nsFrame::GetMaxSize(nsBoxLayoutState& aState)
|
2004-09-28 18:37:50 +00:00
|
|
|
{
|
2007-01-08 02:57:59 +00:00
|
|
|
nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
|
|
|
|
DISPLAY_MAX_SIZE(this, size);
|
2004-09-28 18:37:50 +00:00
|
|
|
// Don't use the cache if we have HTMLReflowState constraints --- they might have changed
|
|
|
|
nsBoxLayoutMetrics *metrics = BoxMetrics();
|
2005-04-28 21:57:22 +00:00
|
|
|
if (!DoesNeedRecalc(metrics->mMaxSize)) {
|
2007-01-08 02:57:59 +00:00
|
|
|
size = metrics->mMaxSize;
|
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
if (IsCollapsed(aState))
|
2007-01-08 02:57:59 +00:00
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
size = nsBox::GetMaxSize(aState);
|
|
|
|
metrics->mMaxSize = size;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-08 02:57:59 +00:00
|
|
|
return size;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
nscoord
|
|
|
|
nsFrame::GetFlex(nsBoxLayoutState& aState)
|
2004-09-28 18:37:50 +00:00
|
|
|
{
|
|
|
|
nsBoxLayoutMetrics *metrics = BoxMetrics();
|
2007-01-31 16:02:42 +00:00
|
|
|
if (!DoesNeedRecalc(metrics->mFlex))
|
|
|
|
return metrics->mFlex;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
metrics->mFlex = nsBox::GetFlex(aState);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
return metrics->mFlex;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
nscoord
|
|
|
|
nsFrame::GetBoxAscent(nsBoxLayoutState& aState)
|
2004-09-28 18:37:50 +00:00
|
|
|
{
|
|
|
|
nsBoxLayoutMetrics *metrics = BoxMetrics();
|
2007-01-31 16:02:42 +00:00
|
|
|
if (!DoesNeedRecalc(metrics->mAscent))
|
|
|
|
return metrics->mAscent;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
if (IsCollapsed(aState)) {
|
2004-09-28 18:37:50 +00:00
|
|
|
metrics->mAscent = 0;
|
|
|
|
} else {
|
|
|
|
// Refresh our caches with new sizes.
|
|
|
|
RefreshSizeCache(aState);
|
|
|
|
metrics->mAscent = metrics->mBlockAscent;
|
|
|
|
}
|
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
return metrics->mAscent;
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFrame::DoLayout(nsBoxLayoutState& aState)
|
|
|
|
{
|
|
|
|
nsRect ourRect(mRect);
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsIRenderingContext* rendContext = aState.GetRenderingContext();
|
2004-09-28 18:37:50 +00:00
|
|
|
nsPresContext* presContext = aState.PresContext();
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsHTMLReflowMetrics desiredSize;
|
2004-09-28 18:37:50 +00:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (rendContext) {
|
2004-09-28 18:37:50 +00:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
rv = BoxReflow(aState, presContext, desiredSize, rendContext,
|
2004-09-28 18:37:50 +00:00
|
|
|
ourRect.x, ourRect.y, ourRect.width, ourRect.height);
|
|
|
|
|
2007-01-31 16:02:42 +00:00
|
|
|
if (IsCollapsed(aState)) {
|
2004-09-28 18:37:50 +00:00
|
|
|
SetSize(nsSize(0, 0));
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// if our child needs to be bigger. This might happend with
|
|
|
|
// wrapping text. There is no way to predict its height until we
|
|
|
|
// reflow it. Now that we know the height reshuffle upward.
|
|
|
|
if (desiredSize.width > ourRect.width ||
|
|
|
|
desiredSize.height > ourRect.height) {
|
|
|
|
|
|
|
|
#ifdef DEBUG_GROW
|
|
|
|
DumpBox(stdout);
|
|
|
|
printf(" GREW from (%d,%d) -> (%d,%d)\n",
|
|
|
|
ourRect.width, ourRect.height,
|
|
|
|
desiredSize.width, desiredSize.height);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (desiredSize.width > ourRect.width)
|
|
|
|
ourRect.width = desiredSize.width;
|
|
|
|
|
|
|
|
if (desiredSize.height > ourRect.height)
|
|
|
|
ourRect.height = desiredSize.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ensure our size is what we think is should be. Someone could have
|
|
|
|
// reset the frame to be smaller or something dumb like that.
|
|
|
|
SetSize(nsSize(ourRect.width, ourRect.height));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SyncLayout(aState);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsFrame::BoxReflow(nsBoxLayoutState& aState,
|
2004-09-28 18:37:50 +00:00
|
|
|
nsPresContext* aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsIRenderingContext* aRenderingContext,
|
2004-09-28 18:37:50 +00:00
|
|
|
nscoord aX,
|
|
|
|
nscoord aY,
|
|
|
|
nscoord aWidth,
|
|
|
|
nscoord aHeight,
|
|
|
|
PRBool aMoveFrame)
|
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
DO_GLOBAL_REFLOW_COUNT("nsBoxToBlockAdaptor");
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_REFLOW
|
|
|
|
nsAdaptorAddIndents();
|
|
|
|
printf("Reflowing: ");
|
|
|
|
nsFrame::ListTag(stdout, mFrame);
|
|
|
|
printf("\n");
|
|
|
|
gIndent2++;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//printf("width=%d, height=%d\n", aWidth, aHeight);
|
|
|
|
/*
|
|
|
|
nsIBox* parent;
|
|
|
|
GetParentBox(&parent);
|
|
|
|
|
|
|
|
// if (parent->GetStateBits() & NS_STATE_CURRENTLY_IN_DEBUG)
|
|
|
|
// printf("In debug\n");
|
|
|
|
*/
|
|
|
|
|
|
|
|
nsBoxLayoutMetrics *metrics = BoxMetrics();
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsReflowStatus status = NS_FRAME_COMPLETE;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
PRBool redrawAfterReflow = PR_FALSE;
|
|
|
|
PRBool redrawNow = PR_FALSE;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
2007-05-06 19:16:51 +00:00
|
|
|
PRBool needsReflow = NS_SUBTREE_DIRTY(this);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
if (redrawNow)
|
|
|
|
Redraw(aState);
|
|
|
|
|
|
|
|
// if we don't need a reflow then
|
|
|
|
// lets see if we are already that size. Yes? then don't even reflow. We are done.
|
|
|
|
if (!needsReflow) {
|
|
|
|
|
|
|
|
if (aWidth != NS_INTRINSICSIZE && aHeight != NS_INTRINSICSIZE) {
|
|
|
|
|
|
|
|
// if the new calculated size has a 0 width or a 0 height
|
|
|
|
if ((metrics->mLastSize.width == 0 || metrics->mLastSize.height == 0) && (aWidth == 0 || aHeight == 0)) {
|
|
|
|
needsReflow = PR_FALSE;
|
|
|
|
aDesiredSize.width = aWidth;
|
|
|
|
aDesiredSize.height = aHeight;
|
|
|
|
SetSize(nsSize(aDesiredSize.width, aDesiredSize.height));
|
|
|
|
} else {
|
|
|
|
aDesiredSize.width = metrics->mLastSize.width;
|
|
|
|
aDesiredSize.height = metrics->mLastSize.height;
|
|
|
|
|
|
|
|
// remove the margin. The rect of our child does not include it but our calculated size does.
|
|
|
|
// don't reflow if we are already the right size
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (metrics->mLastSize.width == aWidth && metrics->mLastSize.height == aHeight)
|
2004-09-28 18:37:50 +00:00
|
|
|
needsReflow = PR_FALSE;
|
|
|
|
else
|
|
|
|
needsReflow = PR_TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// if the width or height are intrinsic alway reflow because
|
|
|
|
// we don't know what it should be.
|
|
|
|
needsReflow = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ok now reflow the child into the spacers calculated space
|
|
|
|
if (needsReflow) {
|
|
|
|
|
|
|
|
aDesiredSize.width = 0;
|
|
|
|
aDesiredSize.height = 0;
|
|
|
|
|
|
|
|
// create a reflow state to tell our child to flow at the given size.
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
// Construct a bogus parent reflow state so that there's a usable
|
|
|
|
// containing block reflow state.
|
|
|
|
nsMargin margin(0,0,0,0);
|
|
|
|
GetMargin(margin);
|
|
|
|
|
|
|
|
nsSize parentSize(aWidth, aHeight);
|
|
|
|
if (parentSize.height != NS_INTRINSICSIZE)
|
|
|
|
parentSize.height += margin.TopBottom();
|
|
|
|
if (parentSize.width != NS_INTRINSICSIZE)
|
|
|
|
parentSize.width += margin.LeftRight();
|
|
|
|
|
|
|
|
nsIFrame *parentFrame = GetParent();
|
|
|
|
nsFrameState savedState = parentFrame->GetStateBits();
|
|
|
|
nsHTMLReflowState parentReflowState(aPresContext, parentFrame,
|
|
|
|
aRenderingContext,
|
|
|
|
parentSize);
|
|
|
|
parentFrame->RemoveStateBits(0xffffffff);
|
|
|
|
parentFrame->AddStateBits(savedState);
|
|
|
|
|
|
|
|
// This may not do very much useful, but it's probably worth trying.
|
|
|
|
if (parentSize.width != NS_INTRINSICSIZE)
|
2007-01-26 00:05:12 +00:00
|
|
|
parentReflowState.SetComputedWidth(parentSize.width);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (parentSize.height != NS_INTRINSICSIZE)
|
2007-08-02 18:08:05 +00:00
|
|
|
parentReflowState.SetComputedHeight(parentSize.height);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
parentReflowState.mComputedMargin.SizeTo(0, 0, 0, 0);
|
2007-01-17 05:19:35 +00:00
|
|
|
// XXX use box methods
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
parentFrame->GetPadding(parentReflowState.mComputedPadding);
|
|
|
|
parentFrame->GetBorder(parentReflowState.mComputedBorderPadding);
|
|
|
|
parentReflowState.mComputedBorderPadding +=
|
|
|
|
parentReflowState.mComputedPadding;
|
|
|
|
|
|
|
|
// XXX Is it OK that this reflow state has no parent reflow state?
|
|
|
|
// (It used to have a bogus parent, skipping all the boxes).
|
2007-04-01 15:15:17 +00:00
|
|
|
nsSize availSize(aWidth, NS_INTRINSICSIZE);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsHTMLReflowState reflowState(aPresContext, this, aRenderingContext,
|
2007-04-01 15:15:17 +00:00
|
|
|
availSize);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
|
|
|
// Construct the parent chain manually since constructing it normally
|
|
|
|
// messes up dimensions.
|
|
|
|
reflowState.parentReflowState = &parentReflowState;
|
|
|
|
reflowState.mCBReflowState = &parentReflowState;
|
2008-04-10 04:39:41 +00:00
|
|
|
reflowState.mReflowDepth = aState.GetReflowDepth();
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
|
|
|
// mComputedWidth and mComputedHeight are content-box, not
|
|
|
|
// border-box
|
2007-01-17 05:19:35 +00:00
|
|
|
if (aWidth != NS_INTRINSICSIZE) {
|
2007-01-26 00:05:12 +00:00
|
|
|
nscoord computedWidth =
|
2007-01-17 05:19:35 +00:00
|
|
|
aWidth - reflowState.mComputedBorderPadding.LeftRight();
|
2009-09-16 15:01:36 +00:00
|
|
|
computedWidth = NS_MAX(computedWidth, 0);
|
2007-01-26 00:05:12 +00:00
|
|
|
reflowState.SetComputedWidth(computedWidth);
|
2007-01-17 05:19:35 +00:00
|
|
|
}
|
2009-06-12 07:33:51 +00:00
|
|
|
|
|
|
|
// Most child frames of box frames (e.g. subdocument or scroll frames)
|
|
|
|
// need to be constrained to the provided size and overflow as necessary.
|
|
|
|
// The one exception are block frames, because we need to know their
|
|
|
|
// natural height excluding any overflow area which may be caused by
|
|
|
|
// various CSS effects such as shadow or outline.
|
|
|
|
if (!IsFrameOfType(eBlockFrame)) {
|
|
|
|
if (aHeight != NS_INTRINSICSIZE) {
|
|
|
|
nscoord computedHeight =
|
|
|
|
aHeight - reflowState.mComputedBorderPadding.TopBottom();
|
2009-09-16 15:01:36 +00:00
|
|
|
computedHeight = NS_MAX(computedHeight, 0);
|
2009-06-12 07:33:51 +00:00
|
|
|
reflowState.SetComputedHeight(computedHeight);
|
|
|
|
} else {
|
|
|
|
reflowState.SetComputedHeight(
|
|
|
|
ComputeSize(aRenderingContext, availSize, availSize.width,
|
|
|
|
nsSize(reflowState.mComputedMargin.LeftRight(),
|
|
|
|
reflowState.mComputedMargin.TopBottom()),
|
|
|
|
nsSize(reflowState.mComputedBorderPadding.LeftRight() -
|
|
|
|
reflowState.mComputedPadding.LeftRight(),
|
|
|
|
reflowState.mComputedBorderPadding.TopBottom() -
|
|
|
|
reflowState.mComputedPadding.TopBottom()),
|
|
|
|
nsSize(reflowState.mComputedPadding.LeftRight(),
|
|
|
|
reflowState.mComputedPadding.TopBottom()),
|
|
|
|
PR_FALSE).height
|
|
|
|
);
|
|
|
|
}
|
2007-01-17 05:19:35 +00:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
|
|
|
// Box layout calls SetRect before Layout, whereas non-box layout
|
|
|
|
// calls SetRect after Reflow.
|
|
|
|
// XXX Perhaps we should be doing this by twiddling the rect back to
|
|
|
|
// mLastSize before calling Reflow and then switching it back, but
|
|
|
|
// However, mLastSize can also be the size passed to BoxReflow by
|
|
|
|
// RefreshSizeCache, so that doesn't really make sense.
|
|
|
|
if (metrics->mLastSize.width != aWidth)
|
|
|
|
reflowState.mFlags.mHResize = PR_TRUE;
|
|
|
|
if (metrics->mLastSize.height != aHeight)
|
|
|
|
reflowState.mFlags.mVResize = PR_TRUE;
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_REFLOW
|
|
|
|
nsAdaptorAddIndents();
|
2007-08-02 18:08:05 +00:00
|
|
|
printf("Size=(%d,%d)\n",reflowState.ComputedWidth(),
|
|
|
|
reflowState.ComputedHeight());
|
2004-09-28 18:37:50 +00:00
|
|
|
nsAdaptorAddIndents();
|
|
|
|
nsAdaptorPrintReason(reflowState);
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// place the child and reflow
|
|
|
|
WillReflow(aPresContext);
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
Reflow(aPresContext, aDesiredSize, reflowState, status);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status");
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
if (redrawAfterReflow) {
|
|
|
|
nsRect r = GetRect();
|
|
|
|
r.width = aDesiredSize.width;
|
|
|
|
r.height = aDesiredSize.height;
|
|
|
|
Redraw(aState, &r);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32 layoutFlags = aState.LayoutFlags();
|
|
|
|
nsContainerFrame::FinishReflowChild(this, aPresContext, &reflowState,
|
|
|
|
aDesiredSize, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME);
|
2007-01-23 04:06:56 +00:00
|
|
|
|
|
|
|
// Save the ascent. (bug 103925)
|
2007-01-31 16:02:42 +00:00
|
|
|
if (IsCollapsed(aState)) {
|
2007-01-23 04:06:56 +00:00
|
|
|
metrics->mAscent = 0;
|
|
|
|
} else {
|
|
|
|
if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
|
|
|
|
if (!nsLayoutUtils::GetFirstLineBaseline(this, &metrics->mAscent))
|
|
|
|
metrics->mAscent = GetBaseline();
|
|
|
|
} else
|
|
|
|
metrics->mAscent = aDesiredSize.ascent;
|
|
|
|
}
|
|
|
|
|
2004-09-28 18:37:50 +00:00
|
|
|
} else {
|
|
|
|
aDesiredSize.ascent = metrics->mBlockAscent;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG_REFLOW
|
|
|
|
if (aHeight != NS_INTRINSICSIZE && aDesiredSize.height != aHeight)
|
|
|
|
{
|
|
|
|
nsAdaptorAddIndents();
|
|
|
|
printf("*****got taller!*****\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
if (aWidth != NS_INTRINSICSIZE && aDesiredSize.width != aWidth)
|
|
|
|
{
|
|
|
|
nsAdaptorAddIndents();
|
|
|
|
printf("*****got wider!******\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (aWidth == NS_INTRINSICSIZE)
|
|
|
|
aWidth = aDesiredSize.width;
|
|
|
|
|
|
|
|
if (aHeight == NS_INTRINSICSIZE)
|
|
|
|
aHeight = aDesiredSize.height;
|
|
|
|
|
|
|
|
metrics->mLastSize.width = aDesiredSize.width;
|
|
|
|
metrics->mLastSize.height = aDesiredSize.height;
|
|
|
|
|
|
|
|
#ifdef DEBUG_REFLOW
|
|
|
|
gIndent2--;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsBoxLayoutMetrics*
|
|
|
|
nsFrame::BoxMetrics() const
|
|
|
|
{
|
|
|
|
nsBoxLayoutMetrics* metrics =
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<nsBoxLayoutMetrics*>(GetProperty(nsGkAtoms::boxMetricsProperty));
|
2004-09-28 18:37:50 +00:00
|
|
|
NS_ASSERTION(metrics, "A box layout method was called but InitBoxMetrics was never called");
|
|
|
|
return metrics;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::SetParent(const nsIFrame* aParent)
|
|
|
|
{
|
|
|
|
PRBool wasBoxWrapped = IsBoxWrapped();
|
|
|
|
nsIFrame::SetParent(aParent);
|
|
|
|
if (!wasBoxWrapped && IsBoxWrapped())
|
|
|
|
InitBoxMetrics(PR_TRUE);
|
|
|
|
else if (wasBoxWrapped && !IsBoxWrapped())
|
2006-12-26 17:47:52 +00:00
|
|
|
DeleteProperty(nsGkAtoms::boxMetricsProperty);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
DeleteBoxMetrics(void *aObject,
|
|
|
|
nsIAtom *aPropertyName,
|
|
|
|
void *aPropertyValue,
|
|
|
|
void *aData)
|
|
|
|
{
|
2007-07-08 07:08:04 +00:00
|
|
|
delete static_cast<nsBoxLayoutMetrics*>(aPropertyValue);
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::InitBoxMetrics(PRBool aClear)
|
|
|
|
{
|
|
|
|
if (aClear)
|
2006-12-26 17:47:52 +00:00
|
|
|
DeleteProperty(nsGkAtoms::boxMetricsProperty);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
|
|
|
nsBoxLayoutMetrics *metrics = new nsBoxLayoutMetrics();
|
2006-12-26 17:47:52 +00:00
|
|
|
SetProperty(nsGkAtoms::boxMetricsProperty, metrics, DeleteBoxMetrics);
|
2004-09-28 18:37:50 +00:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsFrame::MarkIntrinsicWidthsDirty();
|
2004-09-28 18:37:50 +00:00
|
|
|
metrics->mBlockAscent = 0;
|
|
|
|
metrics->mLastSize.SizeTo(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Box layout debugging
|
|
|
|
#ifdef DEBUG_REFLOW
|
|
|
|
PRInt32 gIndent2 = 0;
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAdaptorAddIndents()
|
|
|
|
{
|
|
|
|
for(PRInt32 i=0; i < gIndent2; i++)
|
|
|
|
{
|
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAdaptorPrintReason(nsHTMLReflowState& aReflowState)
|
|
|
|
{
|
|
|
|
char* reflowReasonString;
|
|
|
|
|
|
|
|
switch(aReflowState.reason)
|
|
|
|
{
|
|
|
|
case eReflowReason_Initial:
|
|
|
|
reflowReasonString = "initial";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eReflowReason_Resize:
|
|
|
|
reflowReasonString = "resize";
|
|
|
|
break;
|
|
|
|
case eReflowReason_Dirty:
|
|
|
|
reflowReasonString = "dirty";
|
|
|
|
break;
|
|
|
|
case eReflowReason_StyleChange:
|
|
|
|
reflowReasonString = "stylechange";
|
|
|
|
break;
|
|
|
|
case eReflowReason_Incremental:
|
|
|
|
{
|
2005-02-08 00:59:52 +00:00
|
|
|
switch (aReflowState.reflowCommand->Type()) {
|
2004-09-28 18:37:50 +00:00
|
|
|
case eReflowType_StyleChanged:
|
|
|
|
reflowReasonString = "incremental (StyleChanged)";
|
|
|
|
break;
|
|
|
|
case eReflowType_ReflowDirty:
|
|
|
|
reflowReasonString = "incremental (ReflowDirty)";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
reflowReasonString = "incremental (Unknown)";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
reflowReasonString = "unknown";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("%s",reflowReasonString);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#ifdef DEBUG_LAYOUT
|
|
|
|
void
|
|
|
|
nsFrame::GetBoxName(nsAutoString& aName)
|
|
|
|
{
|
2009-08-20 21:52:48 +00:00
|
|
|
GetFrameName(aName);
|
2004-09-28 18:37:50 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-05-20 16:24:13 +00:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
static void
|
|
|
|
GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize,
|
|
|
|
char* aResult)
|
|
|
|
{
|
2003-11-19 01:20:56 +00:00
|
|
|
const char *nameStr = "";
|
2003-06-13 20:10:01 +00:00
|
|
|
if (aContent) {
|
2003-11-19 01:20:56 +00:00
|
|
|
aContent->Tag()->GetUTF8String(&nameStr);
|
1998-05-20 16:24:13 +00:00
|
|
|
}
|
2003-11-19 01:20:56 +00:00
|
|
|
PR_snprintf(aResult, aResultSize, "%s@%p", nameStr, aFrame);
|
1998-05-20 16:24:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::Trace(const char* aMethod, PRBool aEnter)
|
|
|
|
{
|
|
|
|
if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
|
|
|
|
char tagbuf[40];
|
|
|
|
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
|
|
|
PR_LogPrint("%s: %s %s", tagbuf, aEnter ? "enter" : "exit", aMethod);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::Trace(const char* aMethod, PRBool aEnter, nsReflowStatus aStatus)
|
|
|
|
{
|
|
|
|
if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
|
|
|
|
char tagbuf[40];
|
|
|
|
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
|
|
|
PR_LogPrint("%s: %s %s, status=%scomplete%s",
|
|
|
|
tagbuf, aEnter ? "enter" : "exit", aMethod,
|
|
|
|
NS_FRAME_IS_NOT_COMPLETE(aStatus) ? "not" : "",
|
|
|
|
(NS_FRAME_REFLOW_NEXTINFLOW & aStatus) ? "+reflow" : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::TraceMsg(const char* aFormatString, ...)
|
|
|
|
{
|
|
|
|
if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
|
|
|
|
// Format arguments into a buffer
|
|
|
|
char argbuf[200];
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, aFormatString);
|
|
|
|
PR_vsnprintf(argbuf, sizeof(argbuf), aFormatString, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
char tagbuf[40];
|
|
|
|
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
|
|
|
PR_LogPrint("%s: %s", tagbuf, argbuf);
|
|
|
|
}
|
|
|
|
}
|
1999-07-24 02:37:06 +00:00
|
|
|
|
|
|
|
void
|
2009-07-28 12:53:20 +00:00
|
|
|
nsFrame::VerifyDirtyBitSet(const nsFrameList& aFrameList)
|
1999-07-24 02:37:06 +00:00
|
|
|
{
|
2009-07-28 12:53:20 +00:00
|
|
|
for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
|
|
|
|
NS_ASSERTION(e.get()->GetStateBits() & NS_FRAME_IS_DIRTY,
|
|
|
|
"dirty bit not set");
|
1999-07-24 02:37:06 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-12 08:28:24 +00:00
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
// Start Display Reflow
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
2004-07-31 23:15:21 +00:00
|
|
|
DR_cookie::DR_cookie(nsPresContext* aPresContext,
|
2001-11-14 13:40:03 +00:00
|
|
|
nsIFrame* aFrame,
|
2001-10-29 01:43:59 +00:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsHTMLReflowMetrics& aMetrics,
|
|
|
|
nsReflowStatus& aStatus)
|
2001-11-14 13:40:03 +00:00
|
|
|
:mPresContext(aPresContext), mFrame(aFrame), mReflowState(aReflowState), mMetrics(aMetrics), mStatus(aStatus)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_CTOR(DR_cookie);
|
2001-11-14 13:40:03 +00:00
|
|
|
mValue = nsFrame::DisplayReflowEnter(aPresContext, mFrame, mReflowState);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DR_cookie::~DR_cookie()
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_DTOR(DR_cookie);
|
2001-11-14 13:40:03 +00:00
|
|
|
nsFrame::DisplayReflowExit(mPresContext, mFrame, mMetrics, mStatus, mValue);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
DR_layout_cookie::DR_layout_cookie(nsIFrame* aFrame)
|
|
|
|
: mFrame(aFrame)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(DR_layout_cookie);
|
|
|
|
mValue = nsFrame::DisplayLayoutEnter(mFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_layout_cookie::~DR_layout_cookie()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(DR_layout_cookie);
|
|
|
|
nsFrame::DisplayLayoutExit(mFrame, mValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_intrinsic_width_cookie::DR_intrinsic_width_cookie(
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
const char* aType,
|
|
|
|
nscoord& aResult)
|
|
|
|
: mFrame(aFrame)
|
|
|
|
, mType(aType)
|
|
|
|
, mResult(aResult)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(DR_intrinsic_width_cookie);
|
|
|
|
mValue = nsFrame::DisplayIntrinsicWidthEnter(mFrame, mType);
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_intrinsic_width_cookie::~DR_intrinsic_width_cookie()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(DR_intrinsic_width_cookie);
|
|
|
|
nsFrame::DisplayIntrinsicWidthExit(mFrame, mType, mResult, mValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_intrinsic_size_cookie::DR_intrinsic_size_cookie(
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
const char* aType,
|
|
|
|
nsSize& aResult)
|
|
|
|
: mFrame(aFrame)
|
|
|
|
, mType(aType)
|
|
|
|
, mResult(aResult)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(DR_intrinsic_size_cookie);
|
|
|
|
mValue = nsFrame::DisplayIntrinsicSizeEnter(mFrame, mType);
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_intrinsic_size_cookie::~DR_intrinsic_size_cookie()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(DR_intrinsic_size_cookie);
|
|
|
|
nsFrame::DisplayIntrinsicSizeExit(mFrame, mType, mResult, mValue);
|
|
|
|
}
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
struct DR_FrameTypeInfo;
|
|
|
|
struct DR_FrameTreeNode;
|
|
|
|
struct DR_Rule;
|
|
|
|
|
|
|
|
struct DR_State
|
|
|
|
{
|
|
|
|
DR_State();
|
|
|
|
~DR_State();
|
|
|
|
void Init();
|
|
|
|
void AddFrameTypeInfo(nsIAtom* aFrameType,
|
2004-02-06 23:11:46 +00:00
|
|
|
const char* aFrameNameAbbrev,
|
|
|
|
const char* aFrameName);
|
2001-10-29 01:43:59 +00:00
|
|
|
DR_FrameTypeInfo* GetFrameTypeInfo(nsIAtom* aFrameType);
|
|
|
|
DR_FrameTypeInfo* GetFrameTypeInfo(char* aFrameName);
|
|
|
|
void InitFrameTypeTable();
|
|
|
|
DR_FrameTreeNode* CreateTreeNode(nsIFrame* aFrame,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
const nsHTMLReflowState* aReflowState);
|
2001-10-29 01:43:59 +00:00
|
|
|
void FindMatchingRule(DR_FrameTreeNode& aNode);
|
|
|
|
PRBool RuleMatches(DR_Rule& aRule,
|
|
|
|
DR_FrameTreeNode& aNode);
|
|
|
|
PRBool GetToken(FILE* aFile,
|
|
|
|
char* aBuf);
|
|
|
|
DR_Rule* ParseRule(FILE* aFile);
|
|
|
|
void ParseRulesFile();
|
2009-02-03 14:42:18 +00:00
|
|
|
void AddRule(nsTArray<DR_Rule*>& aRules,
|
|
|
|
DR_Rule& aRule);
|
2001-10-29 01:43:59 +00:00
|
|
|
PRBool IsWhiteSpace(int c);
|
|
|
|
PRBool GetNumber(char* aBuf,
|
|
|
|
PRInt32& aNumber);
|
|
|
|
void PrettyUC(nscoord aSize,
|
|
|
|
char* aBuf);
|
|
|
|
void DisplayFrameTypeInfo(nsIFrame* aFrame,
|
|
|
|
PRInt32 aIndent);
|
|
|
|
void DeleteTreeNode(DR_FrameTreeNode& aNode);
|
|
|
|
|
|
|
|
PRBool mInited;
|
|
|
|
PRBool mActive;
|
|
|
|
PRInt32 mCount;
|
|
|
|
PRInt32 mAssert;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
PRInt32 mIndent;
|
2001-10-29 01:43:59 +00:00
|
|
|
PRBool mIndentUndisplayedFrames;
|
2001-11-14 13:40:03 +00:00
|
|
|
PRBool mDisplayPixelErrors;
|
2009-02-03 14:42:18 +00:00
|
|
|
nsTArray<DR_Rule*> mWildRules;
|
2009-03-12 07:26:29 +00:00
|
|
|
nsTArray<DR_FrameTypeInfo> mFrameTypeTable;
|
2001-10-29 01:43:59 +00:00
|
|
|
// reflow specific state
|
2009-02-03 14:42:18 +00:00
|
|
|
nsTArray<DR_FrameTreeNode*> mFrameTreeLeaves;
|
2001-10-29 01:43:59 +00:00
|
|
|
};
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
static DR_State *DR_state; // the one and only DR_State
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
struct DR_RulePart
|
|
|
|
{
|
|
|
|
DR_RulePart(nsIAtom* aFrameType) : mFrameType(aFrameType), mNext(0) {}
|
|
|
|
void Destroy();
|
|
|
|
|
|
|
|
nsIAtom* mFrameType;
|
|
|
|
DR_RulePart* mNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DR_RulePart::Destroy()
|
|
|
|
{
|
|
|
|
if (mNext) {
|
|
|
|
mNext->Destroy();
|
|
|
|
}
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct DR_Rule
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_Rule() : mLength(0), mTarget(nsnull), mDisplay(PR_FALSE) {
|
|
|
|
MOZ_COUNT_CTOR(DR_Rule);
|
|
|
|
}
|
|
|
|
~DR_Rule() {
|
|
|
|
if (mTarget) mTarget->Destroy();
|
|
|
|
MOZ_COUNT_DTOR(DR_Rule);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
void AddPart(nsIAtom* aFrameType);
|
|
|
|
|
|
|
|
PRUint32 mLength;
|
|
|
|
DR_RulePart* mTarget;
|
|
|
|
PRBool mDisplay;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DR_Rule::AddPart(nsIAtom* aFrameType)
|
|
|
|
{
|
|
|
|
DR_RulePart* newPart = new DR_RulePart(aFrameType);
|
|
|
|
newPart->mNext = mTarget;
|
|
|
|
mTarget = newPart;
|
|
|
|
mLength++;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct DR_FrameTypeInfo
|
|
|
|
{
|
2004-02-06 23:11:46 +00:00
|
|
|
DR_FrameTypeInfo(nsIAtom* aFrmeType, const char* aFrameNameAbbrev, const char* aFrameName);
|
2001-10-31 14:45:12 +00:00
|
|
|
~DR_FrameTypeInfo() {
|
|
|
|
PRInt32 numElements;
|
2009-02-03 14:42:18 +00:00
|
|
|
numElements = mRules.Length();
|
2001-10-31 14:45:12 +00:00
|
|
|
for (PRInt32 i = numElements - 1; i >= 0; i--) {
|
2009-02-03 14:42:18 +00:00
|
|
|
delete mRules.ElementAt(i);
|
2001-10-31 14:45:12 +00:00
|
|
|
}
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
nsIAtom* mType;
|
|
|
|
char mNameAbbrev[16];
|
|
|
|
char mName[32];
|
2009-02-03 14:42:18 +00:00
|
|
|
nsTArray<DR_Rule*> mRules;
|
2009-03-12 07:26:29 +00:00
|
|
|
private:
|
|
|
|
DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&); // NOT USED
|
2001-10-29 01:43:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
DR_FrameTypeInfo::DR_FrameTypeInfo(nsIAtom* aFrameType,
|
2004-02-06 23:11:46 +00:00
|
|
|
const char* aFrameNameAbbrev,
|
|
|
|
const char* aFrameName)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
|
|
|
mType = aFrameType;
|
|
|
|
strcpy(mNameAbbrev, aFrameNameAbbrev);
|
|
|
|
strcpy(mName, aFrameName);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct DR_FrameTreeNode
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_FrameTreeNode(nsIFrame* aFrame, DR_FrameTreeNode* aParent) : mFrame(aFrame), mParent(aParent), mDisplay(0), mIndent(0)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(DR_FrameTreeNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
~DR_FrameTreeNode()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(DR_FrameTreeNode);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
nsIFrame* mFrame;
|
|
|
|
DR_FrameTreeNode* mParent;
|
|
|
|
PRBool mDisplay;
|
|
|
|
PRUint32 mIndent;
|
|
|
|
};
|
|
|
|
|
|
|
|
// DR_State implementation
|
|
|
|
|
|
|
|
DR_State::DR_State()
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
: mInited(PR_FALSE), mActive(PR_FALSE), mCount(0), mAssert(-1), mIndent(0),
|
2001-11-14 13:40:03 +00:00
|
|
|
mIndentUndisplayedFrames(PR_FALSE), mDisplayPixelErrors(PR_FALSE)
|
2003-03-22 15:09:17 +00:00
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(DR_State);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
void DR_State::Init()
|
|
|
|
{
|
|
|
|
char* env = PR_GetEnv("GECKO_DISPLAY_REFLOW_ASSERT");
|
|
|
|
PRInt32 num;
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
|
|
|
mAssert = num;
|
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_ASSERT - invalid value = %s", env);
|
|
|
|
}
|
|
|
|
|
|
|
|
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_START");
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
mIndent = num;
|
2001-10-29 01:43:59 +00:00
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_INDENT_START - invalid value = %s", env);
|
|
|
|
}
|
|
|
|
|
|
|
|
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES");
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
|
|
|
mIndentUndisplayedFrames = num;
|
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES - invalid value = %s", env);
|
|
|
|
}
|
2001-11-14 13:40:03 +00:00
|
|
|
|
|
|
|
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS");
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
|
|
|
mDisplayPixelErrors = num;
|
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS - invalid value = %s", env);
|
|
|
|
}
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
InitFrameTypeTable();
|
|
|
|
ParseRulesFile();
|
|
|
|
mInited = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_State::~DR_State()
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_DTOR(DR_State);
|
2001-10-31 14:45:12 +00:00
|
|
|
PRInt32 numElements, i;
|
2009-02-03 14:42:18 +00:00
|
|
|
numElements = mWildRules.Length();
|
2001-10-31 14:45:12 +00:00
|
|
|
for (i = numElements - 1; i >= 0; i--) {
|
2009-02-03 14:42:18 +00:00
|
|
|
delete mWildRules.ElementAt(i);
|
2001-10-31 14:45:12 +00:00
|
|
|
}
|
2009-02-03 14:42:18 +00:00
|
|
|
numElements = mFrameTreeLeaves.Length();
|
2001-10-31 14:45:12 +00:00
|
|
|
for (i = numElements - 1; i >= 0; i--) {
|
2009-02-03 14:42:18 +00:00
|
|
|
delete mFrameTreeLeaves.ElementAt(i);
|
2001-10-31 14:45:12 +00:00
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::GetNumber(char* aBuf,
|
|
|
|
PRInt32& aNumber)
|
|
|
|
{
|
|
|
|
if (sscanf(aBuf, "%d", &aNumber) > 0)
|
|
|
|
return PR_TRUE;
|
|
|
|
else
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::IsWhiteSpace(int c) {
|
|
|
|
return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::GetToken(FILE* aFile,
|
|
|
|
char* aBuf)
|
|
|
|
{
|
|
|
|
PRBool haveToken = PR_FALSE;
|
|
|
|
aBuf[0] = 0;
|
|
|
|
// get the 1st non whitespace char
|
|
|
|
int c = -1;
|
|
|
|
for (c = getc(aFile); (c > 0) && IsWhiteSpace(c); c = getc(aFile)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c > 0) {
|
|
|
|
haveToken = PR_TRUE;
|
|
|
|
aBuf[0] = c;
|
|
|
|
// get everything up to the next whitespace char
|
|
|
|
PRInt32 cX;
|
|
|
|
for (cX = 1, c = getc(aFile); ; cX++, c = getc(aFile)) {
|
|
|
|
if (c < 0) { // EOF
|
|
|
|
ungetc(' ', aFile);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (IsWhiteSpace(c)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aBuf[cX] = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aBuf[cX] = 0;
|
|
|
|
}
|
|
|
|
return haveToken;
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_Rule* DR_State::ParseRule(FILE* aFile)
|
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
PRInt32 doDisplay;
|
|
|
|
DR_Rule* rule = nsnull;
|
|
|
|
while (GetToken(aFile, buf)) {
|
|
|
|
if (GetNumber(buf, doDisplay)) {
|
|
|
|
if (rule) {
|
2007-10-10 00:00:05 +00:00
|
|
|
rule->mDisplay = !!doDisplay;
|
2001-10-29 01:43:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("unexpected token - %s \n", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!rule) {
|
|
|
|
rule = new DR_Rule;
|
|
|
|
}
|
|
|
|
if (strcmp(buf, "*") == 0) {
|
|
|
|
rule->AddPart(nsnull);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DR_FrameTypeInfo* info = GetFrameTypeInfo(buf);
|
|
|
|
if (info) {
|
|
|
|
rule->AddPart(info->mType);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("invalid frame type - %s \n", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rule;
|
|
|
|
}
|
|
|
|
|
2009-02-03 14:42:18 +00:00
|
|
|
void DR_State::AddRule(nsTArray<DR_Rule*>& aRules,
|
|
|
|
DR_Rule& aRule)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
2009-02-03 14:42:18 +00:00
|
|
|
PRInt32 numRules = aRules.Length();
|
2001-10-29 01:43:59 +00:00
|
|
|
for (PRInt32 ruleX = 0; ruleX < numRules; ruleX++) {
|
2009-02-03 14:42:18 +00:00
|
|
|
DR_Rule* rule = aRules.ElementAt(ruleX);
|
2001-10-29 01:43:59 +00:00
|
|
|
NS_ASSERTION(rule, "program error");
|
|
|
|
if (aRule.mLength > rule->mLength) {
|
2009-02-03 14:42:18 +00:00
|
|
|
aRules.InsertElementAt(ruleX, &aRule);
|
2001-10-29 01:43:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aRules.AppendElement(&aRule);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::ParseRulesFile()
|
|
|
|
{
|
|
|
|
char* path = PR_GetEnv("GECKO_DISPLAY_REFLOW_RULES_FILE");
|
|
|
|
if (path) {
|
|
|
|
FILE* inFile = fopen(path, "r");
|
|
|
|
if (inFile) {
|
|
|
|
for (DR_Rule* rule = ParseRule(inFile); rule; rule = ParseRule(inFile)) {
|
|
|
|
if (rule->mTarget) {
|
|
|
|
nsIAtom* fType = rule->mTarget->mFrameType;
|
|
|
|
if (fType) {
|
|
|
|
DR_FrameTypeInfo* info = GetFrameTypeInfo(fType);
|
|
|
|
if (info) {
|
|
|
|
AddRule(info->mRules, *rule);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
AddRule(mWildRules, *rule);
|
|
|
|
}
|
|
|
|
mActive = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DR_State::AddFrameTypeInfo(nsIAtom* aFrameType,
|
2004-02-06 23:11:46 +00:00
|
|
|
const char* aFrameNameAbbrev,
|
|
|
|
const char* aFrameName)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
2009-03-12 07:26:29 +00:00
|
|
|
mFrameTypeTable.AppendElement(DR_FrameTypeInfo(aFrameType, aFrameNameAbbrev, aFrameName));
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(nsIAtom* aFrameType)
|
|
|
|
{
|
2009-02-03 14:42:18 +00:00
|
|
|
PRInt32 numEntries = mFrameTypeTable.Length();
|
2002-04-16 02:42:09 +00:00
|
|
|
NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
|
2001-10-29 01:43:59 +00:00
|
|
|
for (PRInt32 i = 0; i < numEntries; i++) {
|
2009-03-12 07:26:29 +00:00
|
|
|
DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i);
|
|
|
|
if (info.mType == aFrameType) {
|
|
|
|
return &info;
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
2009-03-12 07:26:29 +00:00
|
|
|
return &mFrameTypeTable.ElementAt(numEntries - 1); // return unknown frame type
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(char* aFrameName)
|
|
|
|
{
|
2009-02-03 14:42:18 +00:00
|
|
|
PRInt32 numEntries = mFrameTypeTable.Length();
|
2002-04-16 02:42:09 +00:00
|
|
|
NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
|
2001-10-29 01:43:59 +00:00
|
|
|
for (PRInt32 i = 0; i < numEntries; i++) {
|
2009-03-12 07:26:29 +00:00
|
|
|
DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i);
|
|
|
|
if ((strcmp(aFrameName, info.mName) == 0) || (strcmp(aFrameName, info.mNameAbbrev) == 0)) {
|
|
|
|
return &info;
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
2009-03-12 07:26:29 +00:00
|
|
|
return &mFrameTypeTable.ElementAt(numEntries - 1); // return unknown frame type
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::InitFrameTypeTable()
|
|
|
|
{
|
2006-12-26 17:47:52 +00:00
|
|
|
AddFrameTypeInfo(nsGkAtoms::blockFrame, "block", "block");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::brFrame, "br", "br");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::bulletFrame, "bullet", "bullet");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::gfxButtonControlFrame, "button", "gfxButtonControl");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::HTMLButtonControlFrame, "HTMLbutton", "HTMLButtonControl");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::HTMLCanvasFrame, "HTMLCanvas","HTMLCanvas");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::subDocumentFrame, "subdoc", "subDocument");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::imageFrame, "img", "image");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::inlineFrame, "inline", "inline");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::letterFrame, "letter", "letter");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::lineFrame, "line", "line");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::listControlFrame, "select", "select");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::objectFrame, "obj", "object");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::pageFrame, "page", "page");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::placeholderFrame, "place", "placeholder");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::positionedInlineFrame, "posInline", "positionedInline");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::canvasFrame, "canvas", "canvas");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::rootFrame, "root", "root");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::scrollFrame, "scroll", "scroll");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableCaptionFrame, "caption", "tableCaption");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableCellFrame, "cell", "tableCell");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::bcTableCellFrame, "bcCell", "bcTableCell");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableColFrame, "col", "tableCol");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableColGroupFrame, "colG", "tableColGroup");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableFrame, "tbl", "table");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableOuterFrame, "tblO", "tableOuter");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableRowGroupFrame, "rowG", "tableRowGroup");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::tableRowFrame, "row", "tableRow");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::textInputFrame, "textCtl", "textInput");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::textFrame, "text", "text");
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::viewportFrame, "VP", "viewport");
|
2008-12-29 15:07:38 +00:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
AddFrameTypeInfo(nsGkAtoms::XULLabelFrame, "XULLabel", "XULLabel");
|
|
|
|
#endif
|
2001-10-29 01:43:59 +00:00
|
|
|
AddFrameTypeInfo(nsnull, "unknown", "unknown");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DR_State::DisplayFrameTypeInfo(nsIFrame* aFrame,
|
|
|
|
PRInt32 aIndent)
|
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
DR_FrameTypeInfo* frameTypeInfo = GetFrameTypeInfo(aFrame->GetType());
|
2001-10-29 01:43:59 +00:00
|
|
|
if (frameTypeInfo) {
|
|
|
|
for (PRInt32 i = 0; i < aIndent; i++) {
|
|
|
|
printf(" ");
|
|
|
|
}
|
2002-04-16 02:42:09 +00:00
|
|
|
if(!strcmp(frameTypeInfo->mNameAbbrev, "unknown")) {
|
2009-08-20 21:52:48 +00:00
|
|
|
if (aFrame) {
|
|
|
|
nsAutoString name;
|
|
|
|
aFrame->GetFrameName(name);
|
2006-02-03 14:18:39 +00:00
|
|
|
printf("%s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)aFrame);
|
2001-12-07 10:02:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
|
2001-12-07 10:02:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
|
2001-12-07 10:02:31 +00:00
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::RuleMatches(DR_Rule& aRule,
|
|
|
|
DR_FrameTreeNode& aNode)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aRule.mTarget, "program error");
|
|
|
|
|
|
|
|
DR_RulePart* rulePart;
|
|
|
|
DR_FrameTreeNode* parentNode;
|
|
|
|
for (rulePart = aRule.mTarget->mNext, parentNode = aNode.mParent;
|
|
|
|
rulePart && parentNode;
|
|
|
|
rulePart = rulePart->mNext, parentNode = parentNode->mParent) {
|
|
|
|
if (rulePart->mFrameType) {
|
|
|
|
if (parentNode->mFrame) {
|
2003-10-31 20:19:18 +00:00
|
|
|
if (rulePart->mFrameType != parentNode->mFrame->GetType()) {
|
2001-10-29 01:43:59 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "program error");
|
|
|
|
}
|
|
|
|
// else wild card match
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::FindMatchingRule(DR_FrameTreeNode& aNode)
|
|
|
|
{
|
|
|
|
if (!aNode.mFrame) {
|
|
|
|
NS_ASSERTION(PR_FALSE, "invalid DR_FrameTreeNode \n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool matchingRule = PR_FALSE;
|
|
|
|
|
2003-10-31 20:19:18 +00:00
|
|
|
DR_FrameTypeInfo* info = GetFrameTypeInfo(aNode.mFrame->GetType());
|
2001-10-29 01:43:59 +00:00
|
|
|
NS_ASSERTION(info, "program error");
|
2009-02-03 14:42:18 +00:00
|
|
|
PRInt32 numRules = info->mRules.Length();
|
2001-10-29 01:43:59 +00:00
|
|
|
for (PRInt32 ruleX = 0; ruleX < numRules; ruleX++) {
|
2009-02-03 14:42:18 +00:00
|
|
|
DR_Rule* rule = info->mRules.ElementAt(ruleX);
|
2001-10-29 01:43:59 +00:00
|
|
|
if (rule && RuleMatches(*rule, aNode)) {
|
|
|
|
aNode.mDisplay = rule->mDisplay;
|
|
|
|
matchingRule = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!matchingRule) {
|
2009-02-03 14:42:18 +00:00
|
|
|
PRInt32 numWildRules = mWildRules.Length();
|
2001-10-29 01:43:59 +00:00
|
|
|
for (PRInt32 ruleX = 0; ruleX < numWildRules; ruleX++) {
|
2009-02-03 14:42:18 +00:00
|
|
|
DR_Rule* rule = mWildRules.ElementAt(ruleX);
|
2001-10-29 01:43:59 +00:00
|
|
|
if (rule && RuleMatches(*rule, aNode)) {
|
|
|
|
aNode.mDisplay = rule->mDisplay;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_FrameTreeNode* DR_State::CreateTreeNode(nsIFrame* aFrame,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
const nsHTMLReflowState* aReflowState)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
|
|
|
// find the frame of the parent reflow state (usually just the parent of aFrame)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
nsIFrame* parentFrame;
|
|
|
|
if (aReflowState) {
|
|
|
|
const nsHTMLReflowState* parentRS = aReflowState->parentReflowState;
|
|
|
|
parentFrame = (parentRS) ? parentRS->frame : nsnull;
|
|
|
|
} else {
|
|
|
|
parentFrame = aFrame->GetParent();
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
// find the parent tree node leaf
|
|
|
|
DR_FrameTreeNode* parentNode = nsnull;
|
2002-01-03 09:00:40 +00:00
|
|
|
|
|
|
|
DR_FrameTreeNode* lastLeaf = nsnull;
|
2009-02-03 14:42:18 +00:00
|
|
|
if(mFrameTreeLeaves.Length())
|
2009-03-12 07:26:29 +00:00
|
|
|
lastLeaf = mFrameTreeLeaves.ElementAt(mFrameTreeLeaves.Length() - 1);
|
2001-10-29 01:43:59 +00:00
|
|
|
if (lastLeaf) {
|
|
|
|
for (parentNode = lastLeaf; parentNode && (parentNode->mFrame != parentFrame); parentNode = parentNode->mParent) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DR_FrameTreeNode* newNode = new DR_FrameTreeNode(aFrame, parentNode);
|
|
|
|
FindMatchingRule(*newNode);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
|
|
|
newNode->mIndent = mIndent;
|
|
|
|
if (newNode->mDisplay || mIndentUndisplayedFrames) {
|
|
|
|
++mIndent;
|
|
|
|
}
|
|
|
|
|
2002-01-03 09:00:40 +00:00
|
|
|
if (lastLeaf && (lastLeaf == parentNode)) {
|
2009-02-03 14:42:18 +00:00
|
|
|
mFrameTreeLeaves.RemoveElementAt(mFrameTreeLeaves.Length() - 1);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
mFrameTreeLeaves.AppendElement(newNode);
|
|
|
|
mCount++;
|
|
|
|
|
|
|
|
return newNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::PrettyUC(nscoord aSize,
|
|
|
|
char* aBuf)
|
|
|
|
{
|
|
|
|
if (NS_UNCONSTRAINEDSIZE == aSize) {
|
|
|
|
strcpy(aBuf, "UC");
|
|
|
|
}
|
|
|
|
else {
|
2004-01-09 14:20:53 +00:00
|
|
|
if ((nscoord)0xdeadbeefU == aSize)
|
2001-12-07 10:02:31 +00:00
|
|
|
{
|
|
|
|
strcpy(aBuf, "deadbeef");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sprintf(aBuf, "%d", aSize);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::DeleteTreeNode(DR_FrameTreeNode& aNode)
|
|
|
|
{
|
|
|
|
mFrameTreeLeaves.RemoveElement(&aNode);
|
2009-02-03 14:42:18 +00:00
|
|
|
PRInt32 numLeaves = mFrameTreeLeaves.Length();
|
|
|
|
if ((0 == numLeaves) || (aNode.mParent != mFrameTreeLeaves.ElementAt(numLeaves - 1))) {
|
2001-10-29 01:43:59 +00:00
|
|
|
mFrameTreeLeaves.AppendElement(aNode.mParent);
|
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
|
|
|
|
if (aNode.mDisplay || mIndentUndisplayedFrames) {
|
|
|
|
--mIndent;
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
// delete the tree node
|
|
|
|
delete &aNode;
|
|
|
|
}
|
|
|
|
|
2001-11-14 13:40:03 +00:00
|
|
|
static void
|
|
|
|
CheckPixelError(nscoord aSize,
|
2007-02-07 07:46:44 +00:00
|
|
|
PRInt32 aPixelToTwips)
|
2001-11-14 13:40:03 +00:00
|
|
|
{
|
|
|
|
if (NS_UNCONSTRAINEDSIZE != aSize) {
|
2007-02-07 07:46:44 +00:00
|
|
|
if ((aSize % aPixelToTwips) > 0) {
|
2001-11-14 13:40:03 +00:00
|
|
|
printf("VALUE %d is not a whole pixel \n", aSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-31 23:15:21 +00:00
|
|
|
static void DisplayReflowEnterPrint(nsPresContext* aPresContext,
|
2001-11-27 01:45:46 +00:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
DR_FrameTreeNode& aTreeNode,
|
|
|
|
PRBool aChanged)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
2001-11-27 01:45:46 +00:00
|
|
|
if (aTreeNode.mDisplay) {
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, aTreeNode.mIndent);
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
char width[16];
|
|
|
|
char height[16];
|
2003-04-06 08:36:19 +00:00
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->PrettyUC(aReflowState.availableWidth, width);
|
|
|
|
DR_state->PrettyUC(aReflowState.availableHeight, height);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
printf("Reflow a=%s,%s ", width, height);
|
2001-10-29 01:43:59 +00:00
|
|
|
|
2007-01-26 00:05:12 +00:00
|
|
|
DR_state->PrettyUC(aReflowState.ComputedWidth(), width);
|
2007-08-02 18:08:05 +00:00
|
|
|
DR_state->PrettyUC(aReflowState.ComputedHeight(), height);
|
2001-10-29 01:43:59 +00:00
|
|
|
printf("c=%s,%s ", width, height);
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
if (aFrame->GetStateBits() & NS_FRAME_IS_DIRTY)
|
|
|
|
printf("dirty ");
|
|
|
|
|
|
|
|
if (aFrame->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN)
|
|
|
|
printf("dirty-children ");
|
|
|
|
|
|
|
|
if (aReflowState.mFlags.mSpecialHeightReflow)
|
|
|
|
printf("special-height ");
|
|
|
|
|
|
|
|
if (aReflowState.mFlags.mHResize)
|
|
|
|
printf("h-resize ");
|
|
|
|
|
|
|
|
if (aReflowState.mFlags.mVResize)
|
|
|
|
printf("v-resize ");
|
|
|
|
|
2004-09-14 02:28:03 +00:00
|
|
|
nsIFrame* inFlow = aFrame->GetPrevInFlow();
|
2001-10-29 01:43:59 +00:00
|
|
|
if (inFlow) {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("pif=%p ", (void*)inFlow);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
2004-09-14 02:28:03 +00:00
|
|
|
inFlow = aFrame->GetNextInFlow();
|
2001-10-29 01:43:59 +00:00
|
|
|
if (inFlow) {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("nif=%p ", (void*)inFlow);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
2001-11-27 01:45:46 +00:00
|
|
|
if (aChanged)
|
|
|
|
printf("CHANGED \n");
|
|
|
|
else
|
2003-03-22 15:09:17 +00:00
|
|
|
printf("cnt=%d \n", DR_state->mCount);
|
|
|
|
if (DR_state->mDisplayPixelErrors) {
|
2007-02-07 07:46:44 +00:00
|
|
|
PRInt32 p2t = aPresContext->AppUnitsPerDevPixel();
|
2001-11-14 13:40:03 +00:00
|
|
|
CheckPixelError(aReflowState.availableWidth, p2t);
|
|
|
|
CheckPixelError(aReflowState.availableHeight, p2t);
|
2007-01-26 00:05:12 +00:00
|
|
|
CheckPixelError(aReflowState.ComputedWidth(), p2t);
|
2007-08-02 18:08:05 +00:00
|
|
|
CheckPixelError(aReflowState.ComputedHeight(), p2t);
|
2001-11-14 13:40:03 +00:00
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
2001-11-27 01:45:46 +00:00
|
|
|
}
|
|
|
|
|
2004-07-31 23:15:21 +00:00
|
|
|
void* nsFrame::DisplayReflowEnter(nsPresContext* aPresContext,
|
2001-11-27 01:45:46 +00:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
const nsHTMLReflowState& aReflowState)
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
if (!DR_state->mInited) DR_state->Init();
|
|
|
|
if (!DR_state->mActive) return nsnull;
|
2001-11-27 01:45:46 +00:00
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "invalid call");
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, &aReflowState);
|
2001-11-27 01:45:46 +00:00
|
|
|
if (treeNode) {
|
|
|
|
DisplayReflowEnterPrint(aPresContext, aFrame, aReflowState, *treeNode, PR_FALSE);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
return treeNode;
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
void* nsFrame::DisplayLayoutEnter(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
if (!DR_state->mInited) DR_state->Init();
|
|
|
|
if (!DR_state->mActive) return nsnull;
|
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "invalid call");
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nsnull);
|
|
|
|
if (treeNode && treeNode->mDisplay) {
|
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
|
|
|
printf("Layout\n");
|
|
|
|
}
|
|
|
|
return treeNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* nsFrame::DisplayIntrinsicWidthEnter(nsIFrame* aFrame,
|
|
|
|
const char* aType)
|
|
|
|
{
|
|
|
|
if (!DR_state->mInited) DR_state->Init();
|
|
|
|
if (!DR_state->mActive) return nsnull;
|
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "invalid call");
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nsnull);
|
|
|
|
if (treeNode && treeNode->mDisplay) {
|
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
|
|
|
printf("Get%sWidth\n", aType);
|
|
|
|
}
|
|
|
|
return treeNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* nsFrame::DisplayIntrinsicSizeEnter(nsIFrame* aFrame,
|
|
|
|
const char* aType)
|
|
|
|
{
|
|
|
|
if (!DR_state->mInited) DR_state->Init();
|
|
|
|
if (!DR_state->mActive) return nsnull;
|
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "invalid call");
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nsnull);
|
|
|
|
if (treeNode && treeNode->mDisplay) {
|
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
|
|
|
printf("Get%sSize\n", aType);
|
|
|
|
}
|
|
|
|
return treeNode;
|
|
|
|
}
|
|
|
|
|
2004-07-31 23:15:21 +00:00
|
|
|
void nsFrame::DisplayReflowExit(nsPresContext* aPresContext,
|
2001-11-14 13:40:03 +00:00
|
|
|
nsIFrame* aFrame,
|
2001-10-29 01:43:59 +00:00
|
|
|
nsHTMLReflowMetrics& aMetrics,
|
|
|
|
nsReflowStatus aStatus,
|
|
|
|
void* aFrameTreeNode)
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
if (!DR_state->mActive) return;
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "DisplayReflowExit - invalid call");
|
|
|
|
if (!aFrameTreeNode) return;
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
|
|
|
|
if (treeNode->mDisplay) {
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
char width[16];
|
|
|
|
char height[16];
|
2003-04-06 08:36:19 +00:00
|
|
|
char x[16];
|
|
|
|
char y[16];
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->PrettyUC(aMetrics.width, width);
|
|
|
|
DR_state->PrettyUC(aMetrics.height, height);
|
2009-01-29 20:39:22 +00:00
|
|
|
printf("Reflow d=%s,%s", width, height);
|
2001-10-29 01:43:59 +00:00
|
|
|
|
2007-07-26 04:03:29 +00:00
|
|
|
if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
|
2009-01-29 20:39:22 +00:00
|
|
|
printf(" status=0x%x", aStatus);
|
2003-04-06 08:36:19 +00:00
|
|
|
}
|
2009-04-06 00:31:50 +00:00
|
|
|
if (aFrame->HasOverflowRect()) {
|
2008-02-20 07:08:55 +00:00
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.x, x);
|
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.y, y);
|
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.width, width);
|
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.height, height);
|
2009-01-29 20:39:22 +00:00
|
|
|
printf(" o=(%s,%s) %s x %s", x, y, width, height);
|
2009-04-06 00:31:50 +00:00
|
|
|
if (aFrame->HasOverflowRect()) {
|
2008-02-20 07:08:55 +00:00
|
|
|
nsRect storedOverflow = aFrame->GetOverflowRect();
|
|
|
|
DR_state->PrettyUC(storedOverflow.x, x);
|
|
|
|
DR_state->PrettyUC(storedOverflow.y, y);
|
|
|
|
DR_state->PrettyUC(storedOverflow.width, width);
|
|
|
|
DR_state->PrettyUC(storedOverflow.height, height);
|
2009-01-29 20:39:22 +00:00
|
|
|
printf(" sto=(%s,%s) %s x %s", x, y, width, height);
|
2008-02-20 07:08:55 +00:00
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
printf("\n");
|
2003-03-22 15:09:17 +00:00
|
|
|
if (DR_state->mDisplayPixelErrors) {
|
2007-02-07 07:46:44 +00:00
|
|
|
PRInt32 p2t = aPresContext->AppUnitsPerDevPixel();
|
2001-11-14 13:40:03 +00:00
|
|
|
CheckPixelError(aMetrics.width, p2t);
|
|
|
|
CheckPixelError(aMetrics.height, p2t);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->DeleteTreeNode(*treeNode);
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 05:38:33 +00:00
|
|
|
void nsFrame::DisplayLayoutExit(nsIFrame* aFrame,
|
|
|
|
void* aFrameTreeNode)
|
|
|
|
{
|
|
|
|
if (!DR_state->mActive) return;
|
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "non-null frame required");
|
|
|
|
if (!aFrameTreeNode) return;
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
|
|
|
|
if (treeNode->mDisplay) {
|
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
|
|
|
nsRect rect = aFrame->GetRect();
|
|
|
|
printf("Layout=%d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height);
|
|
|
|
}
|
|
|
|
DR_state->DeleteTreeNode(*treeNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsFrame::DisplayIntrinsicWidthExit(nsIFrame* aFrame,
|
|
|
|
const char* aType,
|
|
|
|
nscoord aResult,
|
|
|
|
void* aFrameTreeNode)
|
|
|
|
{
|
|
|
|
if (!DR_state->mActive) return;
|
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "non-null frame required");
|
|
|
|
if (!aFrameTreeNode) return;
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
|
|
|
|
if (treeNode->mDisplay) {
|
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
|
|
|
printf("Get%sWidth=%d\n", aType, aResult);
|
|
|
|
}
|
|
|
|
DR_state->DeleteTreeNode(*treeNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsFrame::DisplayIntrinsicSizeExit(nsIFrame* aFrame,
|
|
|
|
const char* aType,
|
|
|
|
nsSize aResult,
|
|
|
|
void* aFrameTreeNode)
|
|
|
|
{
|
|
|
|
if (!DR_state->mActive) return;
|
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "non-null frame required");
|
|
|
|
if (!aFrameTreeNode) return;
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
|
|
|
|
if (treeNode->mDisplay) {
|
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
|
|
|
|
|
|
|
char width[16];
|
|
|
|
char height[16];
|
|
|
|
DR_state->PrettyUC(aResult.width, width);
|
|
|
|
DR_state->PrettyUC(aResult.height, height);
|
|
|
|
printf("Get%sSize=%s,%s\n", aType, width, height);
|
|
|
|
}
|
|
|
|
DR_state->DeleteTreeNode(*treeNode);
|
|
|
|
}
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
/* static */ void
|
|
|
|
nsFrame::DisplayReflowStartup()
|
|
|
|
{
|
|
|
|
DR_state = new DR_State();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
nsFrame::DisplayReflowShutdown()
|
|
|
|
{
|
|
|
|
delete DR_state;
|
|
|
|
DR_state = nsnull;
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
2001-11-27 01:45:46 +00:00
|
|
|
void DR_cookie::Change() const
|
|
|
|
{
|
|
|
|
DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)mValue;
|
|
|
|
if (treeNode && treeNode->mDisplay) {
|
|
|
|
DisplayReflowEnterPrint(mPresContext, mFrame, mReflowState, *treeNode, PR_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
#endif
|
|
|
|
// End Display Reflow
|
|
|
|
|
1998-05-20 16:24:13 +00:00
|
|
|
#endif
|