michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* rendering object for HTML elements */ michael@0: michael@0: #include "nsFrameSetFrame.h" michael@0: michael@0: #include "mozilla/DebugOnly.h" michael@0: #include "mozilla/Likely.h" michael@0: michael@0: #include "nsGenericHTMLElement.h" michael@0: #include "nsAttrValueInlines.h" michael@0: #include "nsLeafFrame.h" michael@0: #include "nsContainerFrame.h" michael@0: #include "nsPresContext.h" michael@0: #include "nsIPresShell.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsStyleConsts.h" michael@0: #include "nsStyleContext.h" michael@0: #include "nsHTMLParts.h" michael@0: #include "nsRenderingContext.h" michael@0: #include "nsIDOMMutationEvent.h" michael@0: #include "nsNameSpaceManager.h" michael@0: #include "nsCSSAnonBoxes.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsStyleSet.h" michael@0: #include "mozilla/dom/Element.h" michael@0: #include "nsDisplayList.h" michael@0: #include "nsNodeUtils.h" michael@0: #include "mozAutoDocUpdate.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "mozilla/dom/HTMLFrameSetElement.h" michael@0: #include "mozilla/LookAndFeel.h" michael@0: #include "mozilla/MouseEvents.h" michael@0: #include "nsSubDocumentFrame.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: michael@0: // masks for mEdgeVisibility michael@0: #define LEFT_VIS 0x0001 michael@0: #define RIGHT_VIS 0x0002 michael@0: #define TOP_VIS 0x0004 michael@0: #define BOTTOM_VIS 0x0008 michael@0: #define ALL_VIS 0x000F michael@0: #define NONE_VIS 0x0000 michael@0: michael@0: /******************************************************************************* michael@0: * nsFramesetDrag michael@0: ******************************************************************************/ michael@0: nsFramesetDrag::nsFramesetDrag() michael@0: { michael@0: UnSet(); michael@0: } michael@0: michael@0: void nsFramesetDrag::Reset(bool aVertical, michael@0: int32_t aIndex, michael@0: int32_t aChange, michael@0: nsHTMLFramesetFrame* aSource) michael@0: { michael@0: mVertical = aVertical; michael@0: mIndex = aIndex; michael@0: mChange = aChange; michael@0: mSource = aSource; michael@0: } michael@0: michael@0: void nsFramesetDrag::UnSet() michael@0: { michael@0: mVertical = true; michael@0: mIndex = -1; michael@0: mChange = 0; michael@0: mSource = nullptr; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * nsHTMLFramesetBorderFrame michael@0: ******************************************************************************/ michael@0: class nsHTMLFramesetBorderFrame : public nsLeafFrame michael@0: { michael@0: public: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: virtual nsresult HandleEvent(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult GetCursor(const nsPoint& aPoint, michael@0: nsIFrame::Cursor& aCursor) MOZ_OVERRIDE; michael@0: michael@0: virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: michael@0: bool GetVisibility() { return mVisibility || mVisibilityOverride; } michael@0: void SetVisibility(bool aVisibility); michael@0: void SetColor(nscolor aColor); michael@0: michael@0: void PaintBorder(nsRenderingContext& aRenderingContext, nsPoint aPt); michael@0: michael@0: protected: michael@0: nsHTMLFramesetBorderFrame(nsStyleContext* aContext, int32_t aWidth, bool aVertical, bool aVisible); michael@0: virtual ~nsHTMLFramesetBorderFrame(); michael@0: virtual nscoord GetIntrinsicWidth() MOZ_OVERRIDE; michael@0: virtual nscoord GetIntrinsicHeight() MOZ_OVERRIDE; michael@0: michael@0: // the prev and next neighbors are indexes into the row (for a horizontal border) or col (for michael@0: // a vertical border) of nsHTMLFramesetFrames or nsHTMLFrames michael@0: int32_t mPrevNeighbor; michael@0: int32_t mNextNeighbor; michael@0: nscolor mColor; michael@0: int32_t mWidth; michael@0: bool mVertical; michael@0: bool mVisibility; michael@0: bool mVisibilityOverride; michael@0: bool mCanResize; michael@0: friend class nsHTMLFramesetFrame; michael@0: }; michael@0: /******************************************************************************* michael@0: * nsHTMLFramesetBlankFrame michael@0: ******************************************************************************/ michael@0: class nsHTMLFramesetBlankFrame : public nsLeafFrame michael@0: { michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsHTMLFramesetBlankFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE michael@0: { michael@0: return MakeFrameName(NS_LITERAL_STRING("FramesetBlank"), aResult); michael@0: } michael@0: #endif michael@0: michael@0: virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: michael@0: protected: michael@0: nsHTMLFramesetBlankFrame(nsStyleContext* aContext) : nsLeafFrame(aContext) {} michael@0: virtual ~nsHTMLFramesetBlankFrame(); michael@0: virtual nscoord GetIntrinsicWidth() MOZ_OVERRIDE; michael@0: virtual nscoord GetIntrinsicHeight() MOZ_OVERRIDE; michael@0: michael@0: friend class nsHTMLFramesetFrame; michael@0: friend class nsHTMLFrameset; michael@0: }; michael@0: michael@0: /******************************************************************************* michael@0: * nsHTMLFramesetFrame michael@0: ******************************************************************************/ michael@0: bool nsHTMLFramesetFrame::gDragInProgress = false; michael@0: #define kFrameResizePref "layout.frames.force_resizability" michael@0: #define DEFAULT_BORDER_WIDTH_PX 6 michael@0: michael@0: nsHTMLFramesetFrame::nsHTMLFramesetFrame(nsStyleContext* aContext) michael@0: : nsContainerFrame(aContext) michael@0: { michael@0: mNumRows = 0; michael@0: mRowSizes = nullptr; michael@0: mNumCols = 0; michael@0: mColSizes = nullptr; michael@0: mEdgeVisibility = 0; michael@0: mParentFrameborder = eFrameborder_Yes; // default michael@0: mParentBorderWidth = -1; // default not set michael@0: mParentBorderColor = NO_COLOR; // default not set michael@0: mFirstDragPoint.x = mFirstDragPoint.y = 0; michael@0: mMinDrag = nsPresContext::CSSPixelsToAppUnits(2); michael@0: mNonBorderChildCount = 0; michael@0: mNonBlankChildCount = 0; michael@0: mDragger = nullptr; michael@0: mChildCount = 0; michael@0: mTopLevelFrameset = nullptr; michael@0: mEdgeColors.Set(NO_COLOR); michael@0: mVerBorders = nullptr; michael@0: mHorBorders = nullptr; michael@0: mChildFrameborder = nullptr; michael@0: mChildBorderColors = nullptr; michael@0: mForceFrameResizability = false; michael@0: } michael@0: michael@0: nsHTMLFramesetFrame::~nsHTMLFramesetFrame() michael@0: { michael@0: delete[] mRowSizes; michael@0: delete[] mColSizes; michael@0: delete[] mVerBorders; michael@0: delete[] mHorBorders; michael@0: delete[] mChildFrameborder; michael@0: delete[] mChildBorderColors; michael@0: michael@0: Preferences::UnregisterCallback(FrameResizePrefCallback, michael@0: kFrameResizePref, this); michael@0: } michael@0: michael@0: NS_QUERYFRAME_HEAD(nsHTMLFramesetFrame) michael@0: NS_QUERYFRAME_ENTRY(nsHTMLFramesetFrame) michael@0: NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame) michael@0: michael@0: // static michael@0: void michael@0: nsHTMLFramesetFrame::FrameResizePrefCallback(const char* aPref, void* aClosure) michael@0: { michael@0: nsHTMLFramesetFrame *frame = michael@0: reinterpret_cast(aClosure); michael@0: michael@0: nsIDocument* doc = frame->mContent->GetDocument(); michael@0: mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true); michael@0: if (doc) { michael@0: nsNodeUtils::AttributeWillChange(frame->GetContent()->AsElement(), michael@0: kNameSpaceID_None, michael@0: nsGkAtoms::frameborder, michael@0: nsIDOMMutationEvent::MODIFICATION); michael@0: } michael@0: michael@0: frame->mForceFrameResizability = michael@0: Preferences::GetBool(kFrameResizePref, frame->mForceFrameResizability); michael@0: michael@0: frame->RecalculateBorderResize(); michael@0: if (doc) { michael@0: nsNodeUtils::AttributeChanged(frame->GetContent()->AsElement(), michael@0: kNameSpaceID_None, michael@0: nsGkAtoms::frameborder, michael@0: nsIDOMMutationEvent::MODIFICATION); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) michael@0: { michael@0: nsContainerFrame::Init(aContent, aParent, aPrevInFlow); michael@0: // find the highest ancestor that is a frameset michael@0: nsIFrame* parentFrame = GetParent(); michael@0: mTopLevelFrameset = this; michael@0: while (parentFrame) { michael@0: nsHTMLFramesetFrame* frameset = do_QueryFrame(parentFrame); michael@0: if (frameset) { michael@0: mTopLevelFrameset = frameset; michael@0: parentFrame = parentFrame->GetParent(); michael@0: } else { michael@0: break; michael@0: } michael@0: } michael@0: michael@0: nsPresContext* presContext = PresContext(); michael@0: nsIPresShell* shell = presContext->PresShell(); michael@0: michael@0: nsFrameborder frameborder = GetFrameBorder(); michael@0: int32_t borderWidth = GetBorderWidth(presContext, false); michael@0: nscolor borderColor = GetBorderColor(); michael@0: michael@0: // Get the rows= cols= data michael@0: HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent); michael@0: NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!"); michael@0: const nsFramesetSpec* rowSpecs = nullptr; michael@0: const nsFramesetSpec* colSpecs = nullptr; michael@0: // GetRowSpec and GetColSpec can fail, but when they do they set michael@0: // mNumRows and mNumCols respectively to 0, so we deal with it fine. michael@0: ourContent->GetRowSpec(&mNumRows, &rowSpecs); michael@0: ourContent->GetColSpec(&mNumCols, &colSpecs); michael@0: michael@0: // Maximum value of mNumRows and mNumCols is NS_MAX_FRAMESET_SPEC_COUNT michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscoord)); michael@0: mRowSizes = new nscoord[mNumRows]; michael@0: mColSizes = new nscoord[mNumCols]; michael@0: michael@0: // Ensure we can't overflow numCells michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT); michael@0: int32_t numCells = mNumRows*mNumCols; michael@0: michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nsHTMLFramesetBorderFrame*)); michael@0: mVerBorders = new nsHTMLFramesetBorderFrame*[mNumCols]; // 1 more than number of ver borders michael@0: michael@0: for (int verX = 0; verX < mNumCols; verX++) michael@0: mVerBorders[verX] = nullptr; michael@0: michael@0: mHorBorders = new nsHTMLFramesetBorderFrame*[mNumRows]; // 1 more than number of hor borders michael@0: michael@0: for (int horX = 0; horX < mNumRows; horX++) michael@0: mHorBorders[horX] = nullptr; michael@0: michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT michael@0: < UINT_MAX / sizeof(int32_t) / NS_MAX_FRAMESET_SPEC_COUNT); michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT michael@0: < UINT_MAX / sizeof(nsFrameborder) / NS_MAX_FRAMESET_SPEC_COUNT); michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT michael@0: < UINT_MAX / sizeof(nsBorderColor) / NS_MAX_FRAMESET_SPEC_COUNT); michael@0: mChildFrameborder = new nsFrameborder[numCells]; michael@0: mChildBorderColors = new nsBorderColor[numCells]; michael@0: michael@0: // create the children frames; skip content which isn't or michael@0: mChildCount = 0; // number of or children michael@0: nsIFrame* frame; michael@0: michael@0: // number of any type of children michael@0: uint32_t numChildren = mContent->GetChildCount(); michael@0: michael@0: for (uint32_t childX = 0; childX < numChildren; childX++) { michael@0: if (mChildCount == numCells) { // we have more or than cells michael@0: // Clear the lazy bits in the remaining children. Also clear michael@0: // the restyle flags, like nsCSSFrameConstructor::ProcessChildren does. michael@0: for (uint32_t i = childX; i < numChildren; i++) { michael@0: nsIContent *child = mContent->GetChildAt(i); michael@0: child->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME); michael@0: if (child->IsElement()) { michael@0: child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS); michael@0: } michael@0: } michael@0: break; michael@0: } michael@0: nsIContent *child = mContent->GetChildAt(childX); michael@0: child->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME); michael@0: // Also clear the restyle flags in the child like michael@0: // nsCSSFrameConstructor::ProcessChildren does. michael@0: if (child->IsElement()) { michael@0: child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS); michael@0: } michael@0: michael@0: // IMPORTANT: This must match the conditions in michael@0: // nsCSSFrameConstructor::ContentAppended/Inserted/Removed michael@0: if (!child->IsHTML()) michael@0: continue; michael@0: michael@0: nsIAtom *tag = child->Tag(); michael@0: if (tag == nsGkAtoms::frameset || tag == nsGkAtoms::frame) { michael@0: nsRefPtr kidSC; michael@0: michael@0: kidSC = shell->StyleSet()->ResolveStyleFor(child->AsElement(), michael@0: mStyleContext); michael@0: if (tag == nsGkAtoms::frameset) { michael@0: frame = NS_NewHTMLFramesetFrame(shell, kidSC); michael@0: michael@0: nsHTMLFramesetFrame* childFrame = (nsHTMLFramesetFrame*)frame; michael@0: childFrame->SetParentFrameborder(frameborder); michael@0: childFrame->SetParentBorderWidth(borderWidth); michael@0: childFrame->SetParentBorderColor(borderColor); michael@0: frame->Init(child, this, nullptr); michael@0: michael@0: mChildBorderColors[mChildCount].Set(childFrame->GetBorderColor()); michael@0: } else { // frame michael@0: frame = NS_NewSubDocumentFrame(shell, kidSC); michael@0: michael@0: frame->Init(child, this, nullptr); michael@0: michael@0: mChildFrameborder[mChildCount] = GetFrameBorder(child); michael@0: mChildBorderColors[mChildCount].Set(GetBorderColor(child)); michael@0: } michael@0: child->SetPrimaryFrame(frame); michael@0: michael@0: mFrames.AppendFrame(nullptr, frame); michael@0: michael@0: mChildCount++; michael@0: } michael@0: } michael@0: michael@0: mNonBlankChildCount = mChildCount; michael@0: // add blank frames for frameset cells that had no content provided michael@0: for (int blankX = mChildCount; blankX < numCells; blankX++) { michael@0: nsRefPtr pseudoStyleContext; michael@0: pseudoStyleContext = shell->StyleSet()-> michael@0: ResolveAnonymousBoxStyle(nsCSSAnonBoxes::framesetBlank, mStyleContext); michael@0: michael@0: // XXX the blank frame is using the content of its parent - at some point it michael@0: // should just have null content, if we support that michael@0: nsHTMLFramesetBlankFrame* blankFrame = new (shell) nsHTMLFramesetBlankFrame(pseudoStyleContext); michael@0: michael@0: blankFrame->Init(mContent, this, nullptr); michael@0: michael@0: mFrames.AppendFrame(nullptr, blankFrame); michael@0: michael@0: mChildBorderColors[mChildCount].Set(NO_COLOR); michael@0: mChildCount++; michael@0: } michael@0: michael@0: mNonBorderChildCount = mChildCount; michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLFramesetFrame::SetInitialChildList(ChildListID aListID, michael@0: nsFrameList& aChildList) michael@0: { michael@0: // We do this weirdness where we create our child frames in Init(). On the michael@0: // other hand, we're going to get a SetInitialChildList() with an empty list michael@0: // and null list name after the frame constructor is done creating us. So michael@0: // just ignore that call. michael@0: if (aListID == kPrincipalList && aChildList.IsEmpty()) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: return nsContainerFrame::SetInitialChildList(aListID, aChildList); michael@0: } michael@0: michael@0: // XXX should this try to allocate twips based on an even pixel boundary? michael@0: void nsHTMLFramesetFrame::Scale(nscoord aDesired, michael@0: int32_t aNumIndicies, michael@0: int32_t* aIndicies, michael@0: int32_t aNumItems, michael@0: int32_t* aItems) michael@0: { michael@0: int32_t actual = 0; michael@0: int32_t i, j; michael@0: // get the actual total michael@0: for (i = 0; i < aNumIndicies; i++) { michael@0: j = aIndicies[i]; michael@0: actual += aItems[j]; michael@0: } michael@0: michael@0: if (actual > 0) { michael@0: float factor = (float)aDesired / (float)actual; michael@0: actual = 0; michael@0: // scale the items up or down michael@0: for (i = 0; i < aNumIndicies; i++) { michael@0: j = aIndicies[i]; michael@0: aItems[j] = NSToCoordRound((float)aItems[j] * factor); michael@0: actual += aItems[j]; michael@0: } michael@0: } else if (aNumIndicies != 0) { michael@0: // All the specs say zero width, but we have to fill up space michael@0: // somehow. Distribute it equally. michael@0: nscoord width = NSToCoordRound((float)aDesired / (float)aNumIndicies); michael@0: actual = width * aNumIndicies; michael@0: for (i = 0; i < aNumIndicies; i++) { michael@0: aItems[aIndicies[i]] = width; michael@0: } michael@0: } michael@0: michael@0: if (aNumIndicies > 0 && aDesired != actual) { michael@0: int32_t unit = (aDesired > actual) ? 1 : -1; michael@0: for (i=0; (i < aNumIndicies) && (aDesired != actual); i++) { michael@0: j = aIndicies[i]; michael@0: if (j < aNumItems) { michael@0: aItems[j] += unit; michael@0: actual += unit; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Translate the rows/cols specs into an array of integer sizes for michael@0: * each cell in the frameset. Sizes are allocated based on the priorities of the michael@0: * specifier - fixed sizes have the highest priority, percentage sizes have the next michael@0: * highest priority and relative sizes have the lowest. michael@0: */ michael@0: void nsHTMLFramesetFrame::CalculateRowCol(nsPresContext* aPresContext, michael@0: nscoord aSize, michael@0: int32_t aNumSpecs, michael@0: const nsFramesetSpec* aSpecs, michael@0: nscoord* aValues) michael@0: { michael@0: // aNumSpecs maximum value is NS_MAX_FRAMESET_SPEC_COUNT michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(int32_t)); michael@0: michael@0: int32_t fixedTotal = 0; michael@0: int32_t numFixed = 0; michael@0: nsAutoArrayPtr fixed(new int32_t[aNumSpecs]); michael@0: int32_t numPercent = 0; michael@0: nsAutoArrayPtr percent(new int32_t[aNumSpecs]); michael@0: int32_t relativeSums = 0; michael@0: int32_t numRelative = 0; michael@0: nsAutoArrayPtr relative(new int32_t[aNumSpecs]); michael@0: michael@0: if (MOZ_UNLIKELY(!fixed || !percent || !relative)) { michael@0: return; // NS_ERROR_OUT_OF_MEMORY michael@0: } michael@0: michael@0: int32_t i, j; michael@0: michael@0: // initialize the fixed, percent, relative indices, allocate the fixed sizes and zero the others michael@0: for (i = 0; i < aNumSpecs; i++) { michael@0: aValues[i] = 0; michael@0: switch (aSpecs[i].mUnit) { michael@0: case eFramesetUnit_Fixed: michael@0: aValues[i] = nsPresContext::CSSPixelsToAppUnits(aSpecs[i].mValue); michael@0: fixedTotal += aValues[i]; michael@0: fixed[numFixed] = i; michael@0: numFixed++; michael@0: break; michael@0: case eFramesetUnit_Percent: michael@0: percent[numPercent] = i; michael@0: numPercent++; michael@0: break; michael@0: case eFramesetUnit_Relative: michael@0: relative[numRelative] = i; michael@0: numRelative++; michael@0: relativeSums += aSpecs[i].mValue; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // scale the fixed sizes if they total too much (or too little and there aren't any percent or relative) michael@0: if ((fixedTotal > aSize) || ((fixedTotal < aSize) && (0 == numPercent) && (0 == numRelative))) { michael@0: Scale(aSize, numFixed, fixed, aNumSpecs, aValues); michael@0: return; michael@0: } michael@0: michael@0: int32_t percentMax = aSize - fixedTotal; michael@0: int32_t percentTotal = 0; michael@0: // allocate the percentage sizes from what is left over from the fixed allocation michael@0: for (i = 0; i < numPercent; i++) { michael@0: j = percent[i]; michael@0: aValues[j] = NSToCoordRound((float)aSpecs[j].mValue * (float)aSize / 100.0f); michael@0: percentTotal += aValues[j]; michael@0: } michael@0: michael@0: // scale the percent sizes if they total too much (or too little and there aren't any relative) michael@0: if ((percentTotal > percentMax) || ((percentTotal < percentMax) && (0 == numRelative))) { michael@0: Scale(percentMax, numPercent, percent, aNumSpecs, aValues); michael@0: return; michael@0: } michael@0: michael@0: int32_t relativeMax = percentMax - percentTotal; michael@0: int32_t relativeTotal = 0; michael@0: // allocate the relative sizes from what is left over from the percent allocation michael@0: for (i = 0; i < numRelative; i++) { michael@0: j = relative[i]; michael@0: aValues[j] = NSToCoordRound((float)aSpecs[j].mValue * (float)relativeMax / (float)relativeSums); michael@0: relativeTotal += aValues[j]; michael@0: } michael@0: michael@0: // scale the relative sizes if they take up too much or too little michael@0: if (relativeTotal != relativeMax) { michael@0: Scale(relativeMax, numRelative, relative, aNumSpecs, aValues); michael@0: } michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Translate the rows/cols integer sizes into an array of specs for michael@0: * each cell in the frameset. Reverse of CalculateRowCol() behaviour. michael@0: * This allows us to maintain the user size info through reflows. michael@0: */ michael@0: void nsHTMLFramesetFrame::GenerateRowCol(nsPresContext* aPresContext, michael@0: nscoord aSize, michael@0: int32_t aNumSpecs, michael@0: const nsFramesetSpec* aSpecs, michael@0: nscoord* aValues, michael@0: nsString& aNewAttr) michael@0: { michael@0: int32_t i; michael@0: michael@0: for (i = 0; i < aNumSpecs; i++) { michael@0: if (!aNewAttr.IsEmpty()) michael@0: aNewAttr.Append(char16_t(',')); michael@0: michael@0: switch (aSpecs[i].mUnit) { michael@0: case eFramesetUnit_Fixed: michael@0: aNewAttr.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(aValues[i])); michael@0: break; michael@0: case eFramesetUnit_Percent: // XXX Only accurate to 1%, need 1 pixel michael@0: case eFramesetUnit_Relative: michael@0: // Add 0.5 to the percentage to make rounding work right. michael@0: aNewAttr.AppendInt(uint32_t((100.0*aValues[i])/aSize + 0.5)); michael@0: aNewAttr.Append(char16_t('%')); michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: michael@0: int32_t nsHTMLFramesetFrame::GetBorderWidth(nsPresContext* aPresContext, michael@0: bool aTakeForcingIntoAccount) michael@0: { michael@0: bool forcing = mForceFrameResizability && aTakeForcingIntoAccount; michael@0: michael@0: if (!forcing) { michael@0: nsFrameborder frameborder = GetFrameBorder(); michael@0: if (frameborder == eFrameborder_No) { michael@0: return 0; michael@0: } michael@0: } michael@0: nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent); michael@0: michael@0: if (content) { michael@0: const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::border); michael@0: if (attr) { michael@0: int32_t intVal = 0; michael@0: if (attr->Type() == nsAttrValue::eInteger) { michael@0: intVal = attr->GetIntegerValue(); michael@0: if (intVal < 0) { michael@0: intVal = 0; michael@0: } michael@0: } michael@0: michael@0: if (forcing && intVal == 0) { michael@0: intVal = DEFAULT_BORDER_WIDTH_PX; michael@0: } michael@0: return nsPresContext::CSSPixelsToAppUnits(intVal); michael@0: } michael@0: } michael@0: michael@0: if (mParentBorderWidth > 0 || michael@0: (mParentBorderWidth == 0 && !forcing)) { michael@0: return mParentBorderWidth; michael@0: } michael@0: michael@0: return nsPresContext::CSSPixelsToAppUnits(DEFAULT_BORDER_WIDTH_PX); michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::GetDesiredSize(nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsHTMLReflowMetrics& aDesiredSize) michael@0: { michael@0: nsHTMLFramesetFrame* framesetParent = do_QueryFrame(GetParent()); michael@0: if (nullptr == framesetParent) { michael@0: if (aPresContext->IsPaginated()) { michael@0: // XXX This needs to be changed when framesets paginate properly michael@0: aDesiredSize.Width() = aReflowState.AvailableWidth(); michael@0: aDesiredSize.Height() = aReflowState.AvailableHeight(); michael@0: } else { michael@0: nsRect area = aPresContext->GetVisibleArea(); michael@0: michael@0: aDesiredSize.Width() = area.width; michael@0: aDesiredSize.Height() = area.height; michael@0: } michael@0: } else { michael@0: nsSize size; michael@0: framesetParent->GetSizeOfChild(this, size); michael@0: aDesiredSize.Width() = size.width; michael@0: aDesiredSize.Height() = size.height; michael@0: } michael@0: } michael@0: michael@0: // only valid for non border children michael@0: void nsHTMLFramesetFrame::GetSizeOfChildAt(int32_t aIndexInParent, michael@0: nsSize& aSize, michael@0: nsIntPoint& aCellIndex) michael@0: { michael@0: int32_t row = aIndexInParent / mNumCols; michael@0: int32_t col = aIndexInParent - (row * mNumCols); // remainder from dividing index by mNumCols michael@0: if ((row < mNumRows) && (col < mNumCols)) { michael@0: aSize.width = mColSizes[col]; michael@0: aSize.height = mRowSizes[row]; michael@0: aCellIndex.x = col; michael@0: aCellIndex.y = row; michael@0: } else { michael@0: aSize.width = aSize.height = 0; michael@0: aCellIndex.x = aCellIndex.y = 0; michael@0: } michael@0: } michael@0: michael@0: // only valid for non border children michael@0: void nsHTMLFramesetFrame::GetSizeOfChild(nsIFrame* aChild, michael@0: nsSize& aSize) michael@0: { michael@0: // Reflow only creates children frames for and content. michael@0: // this assumption is used here michael@0: int i = 0; michael@0: for (nsIFrame* child = mFrames.FirstChild(); child; michael@0: child = child->GetNextSibling()) { michael@0: if (aChild == child) { michael@0: nsIntPoint ignore; michael@0: GetSizeOfChildAt(i, aSize, ignore); michael@0: return; michael@0: } michael@0: i++; michael@0: } michael@0: aSize.width = 0; michael@0: aSize.height = 0; michael@0: } michael@0: michael@0: michael@0: nsresult nsHTMLFramesetFrame::HandleEvent(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aEventStatus); michael@0: if (mDragger) { michael@0: // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN michael@0: switch (aEvent->message) { michael@0: case NS_MOUSE_MOVE: michael@0: MouseDrag(aPresContext, aEvent); michael@0: break; michael@0: case NS_MOUSE_BUTTON_UP: michael@0: if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) { michael@0: EndMouseDrag(aPresContext); michael@0: } michael@0: break; michael@0: } michael@0: *aEventStatus = nsEventStatus_eConsumeNoDefault; michael@0: } else { michael@0: *aEventStatus = nsEventStatus_eIgnore; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLFramesetFrame::GetCursor(const nsPoint& aPoint, michael@0: nsIFrame::Cursor& aCursor) michael@0: { michael@0: if (mDragger) { michael@0: aCursor.mCursor = (mDragger->mVertical) ? NS_STYLE_CURSOR_EW_RESIZE : NS_STYLE_CURSOR_NS_RESIZE; michael@0: } else { michael@0: aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) michael@0: { michael@0: BuildDisplayListForInline(aBuilder, aDirtyRect, aLists); michael@0: michael@0: if (mDragger && aBuilder->IsForEventDelivery()) { michael@0: aLists.Content()->AppendNewToTop( michael@0: new (aBuilder) nsDisplayEventReceiver(aBuilder, this)); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame* aChild, michael@0: nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsPoint& aOffset, michael@0: nsSize& aSize, michael@0: nsIntPoint* aCellIndex) michael@0: { michael@0: // reflow the child michael@0: nsHTMLReflowState reflowState(aPresContext, aReflowState, aChild, aSize); michael@0: reflowState.SetComputedWidth(std::max(0, aSize.width - reflowState.ComputedPhysicalBorderPadding().LeftRight())); michael@0: reflowState.SetComputedHeight(std::max(0, aSize.height - reflowState.ComputedPhysicalBorderPadding().TopBottom())); michael@0: nsHTMLReflowMetrics metrics(aReflowState); michael@0: metrics.Width() = aSize.width; michael@0: metrics.Height() = aSize.height; michael@0: nsReflowStatus status; michael@0: michael@0: ReflowChild(aChild, aPresContext, metrics, reflowState, aOffset.x, michael@0: aOffset.y, 0, status); michael@0: NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status"); michael@0: michael@0: // Place and size the child michael@0: metrics.Width() = aSize.width; michael@0: metrics.Height() = aSize.height; michael@0: FinishReflowChild(aChild, aPresContext, metrics, nullptr, aOffset.x, aOffset.y, 0); michael@0: } michael@0: michael@0: static michael@0: nsFrameborder GetFrameBorderHelper(nsGenericHTMLElement* aContent) michael@0: { michael@0: if (nullptr != aContent) { michael@0: const nsAttrValue* attr = aContent->GetParsedAttr(nsGkAtoms::frameborder); michael@0: if (attr && attr->Type() == nsAttrValue::eEnum) { michael@0: switch (attr->GetEnumValue()) michael@0: { michael@0: case NS_STYLE_FRAME_YES: michael@0: case NS_STYLE_FRAME_1: michael@0: return eFrameborder_Yes; michael@0: break; michael@0: michael@0: case NS_STYLE_FRAME_NO: michael@0: case NS_STYLE_FRAME_0: michael@0: return eFrameborder_No; michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: return eFrameborder_Notset; michael@0: } michael@0: michael@0: nsFrameborder nsHTMLFramesetFrame::GetFrameBorder() michael@0: { michael@0: nsFrameborder result = eFrameborder_Notset; michael@0: nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent); michael@0: michael@0: if (content) { michael@0: result = GetFrameBorderHelper(content); michael@0: } michael@0: if (eFrameborder_Notset == result) { michael@0: return mParentFrameborder; michael@0: } michael@0: return result; michael@0: } michael@0: michael@0: nsFrameborder nsHTMLFramesetFrame::GetFrameBorder(nsIContent* aContent) michael@0: { michael@0: nsFrameborder result = eFrameborder_Notset; michael@0: michael@0: nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(aContent); michael@0: michael@0: if (content) { michael@0: result = GetFrameBorderHelper(content); michael@0: } michael@0: if (eFrameborder_Notset == result) { michael@0: return GetFrameBorder(); michael@0: } michael@0: return result; michael@0: } michael@0: michael@0: nscolor nsHTMLFramesetFrame::GetBorderColor() michael@0: { michael@0: nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent); michael@0: michael@0: if (content) { michael@0: const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::bordercolor); michael@0: if (attr) { michael@0: nscolor color; michael@0: if (attr->GetColorValue(color)) { michael@0: return color; michael@0: } michael@0: } michael@0: } michael@0: michael@0: return mParentBorderColor; michael@0: } michael@0: michael@0: nscolor nsHTMLFramesetFrame::GetBorderColor(nsIContent* aContent) michael@0: { michael@0: nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(aContent); michael@0: michael@0: if (content) { michael@0: const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::bordercolor); michael@0: if (attr) { michael@0: nscolor color; michael@0: if (attr->GetColorValue(color)) { michael@0: return color; michael@0: } michael@0: } michael@0: } michael@0: return GetBorderColor(); michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) michael@0: { michael@0: DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame"); michael@0: DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); michael@0: nsIPresShell *shell = aPresContext->PresShell(); michael@0: nsStyleSet *styleSet = shell->StyleSet(); michael@0: michael@0: mParent->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT); michael@0: michael@0: //printf("FramesetFrame2::Reflow %X (%d,%d) \n", this, aReflowState.AvailableWidth(), aReflowState.AvailableHeight()); michael@0: // Always get the size so that the caller knows how big we are michael@0: GetDesiredSize(aPresContext, aReflowState, aDesiredSize); michael@0: michael@0: nscoord width = (aDesiredSize.Width() <= aReflowState.AvailableWidth()) michael@0: ? aDesiredSize.Width() : aReflowState.AvailableWidth(); michael@0: nscoord height = (aDesiredSize.Height() <= aReflowState.AvailableHeight()) michael@0: ? aDesiredSize.Height() : aReflowState.AvailableHeight(); michael@0: michael@0: bool firstTime = (GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0; michael@0: if (firstTime) { michael@0: Preferences::RegisterCallback(FrameResizePrefCallback, michael@0: kFrameResizePref, this); michael@0: mForceFrameResizability = Preferences::GetBool(kFrameResizePref); michael@0: } michael@0: michael@0: // subtract out the width of all of the potential borders. There are michael@0: // only borders between s. There are none on the edges (e.g the michael@0: // leftmost has no left border). michael@0: int32_t borderWidth = GetBorderWidth(aPresContext, true); michael@0: michael@0: width -= (mNumCols - 1) * borderWidth; michael@0: if (width < 0) width = 0; michael@0: michael@0: height -= (mNumRows - 1) * borderWidth; michael@0: if (height < 0) height = 0; michael@0: michael@0: HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent); michael@0: NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!"); michael@0: const nsFramesetSpec* rowSpecs = nullptr; michael@0: const nsFramesetSpec* colSpecs = nullptr; michael@0: int32_t rows = 0; michael@0: int32_t cols = 0; michael@0: ourContent->GetRowSpec(&rows, &rowSpecs); michael@0: ourContent->GetColSpec(&cols, &colSpecs); michael@0: // If the number of cols or rows has changed, the frame for the frameset michael@0: // will be re-created. michael@0: if (mNumRows != rows || mNumCols != cols) { michael@0: aStatus = NS_FRAME_COMPLETE; michael@0: mDrag.UnSet(); michael@0: NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); michael@0: return NS_OK; michael@0: } michael@0: michael@0: CalculateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes); michael@0: CalculateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes); michael@0: michael@0: nsAutoArrayPtr verBordersVis; // vertical borders visibility michael@0: nsAutoArrayPtr verBorderColors; michael@0: nsAutoArrayPtr horBordersVis; // horizontal borders visibility michael@0: nsAutoArrayPtr horBorderColors; michael@0: nscolor borderColor = GetBorderColor(); michael@0: nsFrameborder frameborder = GetFrameBorder(); michael@0: michael@0: if (firstTime) { michael@0: // Check for overflow in memory allocations using mNumCols and mNumRows michael@0: // which have a maxium value of NS_MAX_FRAMESET_SPEC_COUNT. michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(bool)); michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscolor)); michael@0: michael@0: verBordersVis = new bool[mNumCols]; michael@0: NS_ENSURE_TRUE(verBordersVis, NS_ERROR_OUT_OF_MEMORY); michael@0: verBorderColors = new nscolor[mNumCols]; michael@0: NS_ENSURE_TRUE(verBorderColors, NS_ERROR_OUT_OF_MEMORY); michael@0: for (int verX = 0; verX < mNumCols; verX++) { michael@0: verBordersVis[verX] = false; michael@0: verBorderColors[verX] = NO_COLOR; michael@0: } michael@0: michael@0: horBordersVis = new bool[mNumRows]; michael@0: NS_ENSURE_TRUE(horBordersVis, NS_ERROR_OUT_OF_MEMORY); michael@0: horBorderColors = new nscolor[mNumRows]; michael@0: NS_ENSURE_TRUE(horBorderColors, NS_ERROR_OUT_OF_MEMORY); michael@0: for (int horX = 0; horX < mNumRows; horX++) { michael@0: horBordersVis[horX] = false; michael@0: horBorderColors[horX] = NO_COLOR; michael@0: } michael@0: } michael@0: michael@0: // reflow the children michael@0: int32_t lastRow = 0; michael@0: int32_t lastCol = 0; michael@0: int32_t borderChildX = mNonBorderChildCount; // index of border children michael@0: nsHTMLFramesetBorderFrame* borderFrame = nullptr; michael@0: nsPoint offset(0,0); michael@0: nsSize size, lastSize; michael@0: nsIFrame* child = mFrames.FirstChild(); michael@0: michael@0: for (int32_t childX = 0; childX < mNonBorderChildCount; childX++) { michael@0: nsIntPoint cellIndex; michael@0: GetSizeOfChildAt(childX, size, cellIndex); michael@0: michael@0: if (lastRow != cellIndex.y) { // changed to next row michael@0: offset.x = 0; michael@0: offset.y += lastSize.height; michael@0: if (firstTime) { // create horizontal border michael@0: michael@0: nsRefPtr pseudoStyleContext; michael@0: pseudoStyleContext = styleSet-> michael@0: ResolveAnonymousBoxStyle(nsCSSAnonBoxes::horizontalFramesetBorder, michael@0: mStyleContext); michael@0: michael@0: borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext, michael@0: borderWidth, michael@0: false, michael@0: false); michael@0: borderFrame->Init(mContent, this, nullptr); michael@0: mChildCount++; michael@0: mFrames.AppendFrame(nullptr, borderFrame); michael@0: mHorBorders[cellIndex.y-1] = borderFrame; michael@0: // set the neighbors for determining drag boundaries michael@0: borderFrame->mPrevNeighbor = lastRow; michael@0: borderFrame->mNextNeighbor = cellIndex.y; michael@0: } else { michael@0: borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX); michael@0: borderFrame->mWidth = borderWidth; michael@0: borderChildX++; michael@0: } michael@0: nsSize borderSize(aDesiredSize.Width(), borderWidth); michael@0: ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize); michael@0: borderFrame = nullptr; michael@0: offset.y += borderWidth; michael@0: } else { michael@0: if (cellIndex.x > 0) { // moved to next col in same row michael@0: if (0 == cellIndex.y) { // in 1st row michael@0: if (firstTime) { // create vertical border michael@0: michael@0: nsRefPtr pseudoStyleContext; michael@0: pseudoStyleContext = styleSet-> michael@0: ResolveAnonymousBoxStyle(nsCSSAnonBoxes::verticalFramesetBorder, michael@0: mStyleContext); michael@0: michael@0: borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext, michael@0: borderWidth, michael@0: true, michael@0: false); michael@0: borderFrame->Init(mContent, this, nullptr); michael@0: mChildCount++; michael@0: mFrames.AppendFrame(nullptr, borderFrame); michael@0: mVerBorders[cellIndex.x-1] = borderFrame; michael@0: // set the neighbors for determining drag boundaries michael@0: borderFrame->mPrevNeighbor = lastCol; michael@0: borderFrame->mNextNeighbor = cellIndex.x; michael@0: } else { michael@0: borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX); michael@0: borderFrame->mWidth = borderWidth; michael@0: borderChildX++; michael@0: } michael@0: nsSize borderSize(borderWidth, aDesiredSize.Height()); michael@0: ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize); michael@0: borderFrame = nullptr; michael@0: } michael@0: offset.x += borderWidth; michael@0: } michael@0: } michael@0: michael@0: ReflowPlaceChild(child, aPresContext, aReflowState, offset, size, &cellIndex); michael@0: michael@0: if (firstTime) { michael@0: int32_t childVis; michael@0: nsHTMLFramesetFrame* framesetFrame = do_QueryFrame(child); michael@0: nsSubDocumentFrame* subdocFrame; michael@0: if (framesetFrame) { michael@0: childVis = framesetFrame->mEdgeVisibility; michael@0: mChildBorderColors[childX] = framesetFrame->mEdgeColors; michael@0: } else if ((subdocFrame = do_QueryFrame(child))) { michael@0: if (eFrameborder_Yes == mChildFrameborder[childX]) { michael@0: childVis = ALL_VIS; michael@0: } else if (eFrameborder_No == mChildFrameborder[childX]) { michael@0: childVis = NONE_VIS; michael@0: } else { // notset michael@0: childVis = (eFrameborder_No == frameborder) ? NONE_VIS : ALL_VIS; michael@0: } michael@0: } else { // blank michael@0: DebugOnly blank; michael@0: MOZ_ASSERT(blank = do_QueryFrame(child), "unexpected child frame type"); michael@0: childVis = NONE_VIS; michael@0: } michael@0: nsBorderColor childColors = mChildBorderColors[childX]; michael@0: // set the visibility, color of our edge borders based on children michael@0: if (0 == cellIndex.x) { michael@0: if (!(mEdgeVisibility & LEFT_VIS)) { michael@0: mEdgeVisibility |= (LEFT_VIS & childVis); michael@0: } michael@0: if (NO_COLOR == mEdgeColors.mLeft) { michael@0: mEdgeColors.mLeft = childColors.mLeft; michael@0: } michael@0: } michael@0: if (0 == cellIndex.y) { michael@0: if (!(mEdgeVisibility & TOP_VIS)) { michael@0: mEdgeVisibility |= (TOP_VIS & childVis); michael@0: } michael@0: if (NO_COLOR == mEdgeColors.mTop) { michael@0: mEdgeColors.mTop = childColors.mTop; michael@0: } michael@0: } michael@0: if (mNumCols-1 == cellIndex.x) { michael@0: if (!(mEdgeVisibility & RIGHT_VIS)) { michael@0: mEdgeVisibility |= (RIGHT_VIS & childVis); michael@0: } michael@0: if (NO_COLOR == mEdgeColors.mRight) { michael@0: mEdgeColors.mRight = childColors.mRight; michael@0: } michael@0: } michael@0: if (mNumRows-1 == cellIndex.y) { michael@0: if (!(mEdgeVisibility & BOTTOM_VIS)) { michael@0: mEdgeVisibility |= (BOTTOM_VIS & childVis); michael@0: } michael@0: if (NO_COLOR == mEdgeColors.mBottom) { michael@0: mEdgeColors.mBottom = childColors.mBottom; michael@0: } michael@0: } michael@0: // set the visibility of borders that the child may affect michael@0: if (childVis & RIGHT_VIS) { michael@0: verBordersVis[cellIndex.x] = true; michael@0: } michael@0: if (childVis & BOTTOM_VIS) { michael@0: horBordersVis[cellIndex.y] = true; michael@0: } michael@0: if ((cellIndex.x > 0) && (childVis & LEFT_VIS)) { michael@0: verBordersVis[cellIndex.x-1] = true; michael@0: } michael@0: if ((cellIndex.y > 0) && (childVis & TOP_VIS)) { michael@0: horBordersVis[cellIndex.y-1] = true; michael@0: } michael@0: // set the colors of borders that the child may affect michael@0: if (NO_COLOR == verBorderColors[cellIndex.x]) { michael@0: verBorderColors[cellIndex.x] = mChildBorderColors[childX].mRight; michael@0: } michael@0: if (NO_COLOR == horBorderColors[cellIndex.y]) { michael@0: horBorderColors[cellIndex.y] = mChildBorderColors[childX].mBottom; michael@0: } michael@0: if ((cellIndex.x > 0) && (NO_COLOR == verBorderColors[cellIndex.x-1])) { michael@0: verBorderColors[cellIndex.x-1] = mChildBorderColors[childX].mLeft; michael@0: } michael@0: if ((cellIndex.y > 0) && (NO_COLOR == horBorderColors[cellIndex.y-1])) { michael@0: horBorderColors[cellIndex.y-1] = mChildBorderColors[childX].mTop; michael@0: } michael@0: } michael@0: lastRow = cellIndex.y; michael@0: lastCol = cellIndex.x; michael@0: lastSize = size; michael@0: offset.x += size.width; michael@0: child = child->GetNextSibling(); michael@0: } michael@0: michael@0: if (firstTime) { michael@0: nscolor childColor; michael@0: // set the visibility, color, mouse sensitivity of borders michael@0: for (int verX = 0; verX < mNumCols-1; verX++) { michael@0: if (mVerBorders[verX]) { michael@0: mVerBorders[verX]->SetVisibility(verBordersVis[verX]); michael@0: if (mForceFrameResizability) { michael@0: mVerBorders[verX]->mVisibilityOverride = true; michael@0: } else { michael@0: SetBorderResize(mVerBorders[verX]); michael@0: } michael@0: childColor = (NO_COLOR == verBorderColors[verX]) ? borderColor : verBorderColors[verX]; michael@0: mVerBorders[verX]->SetColor(childColor); michael@0: } michael@0: } michael@0: for (int horX = 0; horX < mNumRows-1; horX++) { michael@0: if (mHorBorders[horX]) { michael@0: mHorBorders[horX]->SetVisibility(horBordersVis[horX]); michael@0: if (mForceFrameResizability) { michael@0: mHorBorders[horX]->mVisibilityOverride = true; michael@0: } else { michael@0: SetBorderResize(mHorBorders[horX]); michael@0: } michael@0: childColor = (NO_COLOR == horBorderColors[horX]) ? borderColor : horBorderColors[horX]; michael@0: mHorBorders[horX]->SetColor(childColor); michael@0: } michael@0: } michael@0: michael@0: delete[] mChildFrameborder; michael@0: delete[] mChildBorderColors; michael@0: michael@0: mChildFrameborder = nullptr; michael@0: mChildBorderColors = nullptr; michael@0: } michael@0: michael@0: aStatus = NS_FRAME_COMPLETE; michael@0: mDrag.UnSet(); michael@0: michael@0: aDesiredSize.SetOverflowAreasToDesiredBounds(); michael@0: FinishAndStoreOverflow(&aDesiredSize); michael@0: michael@0: NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsIAtom* michael@0: nsHTMLFramesetFrame::GetType() const michael@0: { michael@0: return nsGkAtoms::frameSetFrame; michael@0: } michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: nsresult michael@0: nsHTMLFramesetFrame::GetFrameName(nsAString& aResult) const michael@0: { michael@0: return MakeFrameName(NS_LITERAL_STRING("Frameset"), aResult); michael@0: } michael@0: #endif michael@0: michael@0: bool michael@0: nsHTMLFramesetFrame::IsLeaf() const michael@0: { michael@0: // We handle constructing our kids manually michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: nsHTMLFramesetFrame::CanResize(bool aVertical, michael@0: bool aLeft) michael@0: { michael@0: int32_t childX; michael@0: int32_t startX; michael@0: if (aVertical) { michael@0: startX = (aLeft) ? 0 : mNumCols-1; michael@0: for (childX = startX; childX < mNonBorderChildCount; childX += mNumCols) { michael@0: if (!CanChildResize(aVertical, aLeft, childX)) { michael@0: return false; michael@0: } michael@0: } michael@0: } else { michael@0: startX = (aLeft) ? 0 : (mNumRows - 1) * mNumCols; michael@0: int32_t endX = startX + mNumCols; michael@0: for (childX = startX; childX < endX; childX++) { michael@0: if (!CanChildResize(aVertical, aLeft, childX)) { michael@0: return false; michael@0: } michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: nsHTMLFramesetFrame::GetNoResize(nsIFrame* aChildFrame) michael@0: { michael@0: nsIContent* content = aChildFrame->GetContent(); michael@0: michael@0: return content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::noresize); michael@0: } michael@0: michael@0: bool michael@0: nsHTMLFramesetFrame::CanChildResize(bool aVertical, bool aLeft, int32_t aChildX) michael@0: { michael@0: nsIFrame* child = mFrames.FrameAt(aChildX); michael@0: nsHTMLFramesetFrame* frameset = do_QueryFrame(child); michael@0: return frameset ? frameset->CanResize(aVertical, aLeft) : !GetNoResize(child); michael@0: } michael@0: michael@0: // This calculates and sets the resizability of all border frames michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::RecalculateBorderResize() michael@0: { michael@0: if (!mContent) { michael@0: return; michael@0: } michael@0: michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT); michael@0: PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT michael@0: < UINT_MAX / sizeof(int32_t) / NS_MAX_FRAMESET_SPEC_COUNT); michael@0: // set the visibility and mouse sensitivity of borders michael@0: int32_t verX; michael@0: for (verX = 0; verX < mNumCols-1; verX++) { michael@0: if (mVerBorders[verX]) { michael@0: mVerBorders[verX]->mCanResize = true; michael@0: if (mForceFrameResizability) { michael@0: mVerBorders[verX]->mVisibilityOverride = true; michael@0: } else { michael@0: mVerBorders[verX]->mVisibilityOverride = false; michael@0: SetBorderResize(mVerBorders[verX]); michael@0: } michael@0: } michael@0: } michael@0: int32_t horX; michael@0: for (horX = 0; horX < mNumRows-1; horX++) { michael@0: if (mHorBorders[horX]) { michael@0: mHorBorders[horX]->mCanResize = true; michael@0: if (mForceFrameResizability) { michael@0: mHorBorders[horX]->mVisibilityOverride = true; michael@0: } else { michael@0: mHorBorders[horX]->mVisibilityOverride = false; michael@0: SetBorderResize(mHorBorders[horX]); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::SetBorderResize(nsHTMLFramesetBorderFrame* aBorderFrame) michael@0: { michael@0: if (aBorderFrame->mVertical) { michael@0: for (int rowX = 0; rowX < mNumRows; rowX++) { michael@0: int32_t childX = aBorderFrame->mPrevNeighbor + (rowX * mNumCols); michael@0: if (!CanChildResize(true, false, childX) || michael@0: !CanChildResize(true, true, childX+1)) { michael@0: aBorderFrame->mCanResize = false; michael@0: } michael@0: } michael@0: } else { michael@0: int32_t childX = aBorderFrame->mPrevNeighbor * mNumCols; michael@0: int32_t endX = childX + mNumCols; michael@0: for (; childX < endX; childX++) { michael@0: if (!CanChildResize(false, false, childX)) { michael@0: aBorderFrame->mCanResize = false; michael@0: } michael@0: } michael@0: endX = endX + mNumCols; michael@0: for (; childX < endX; childX++) { michael@0: if (!CanChildResize(false, true, childX)) { michael@0: aBorderFrame->mCanResize = false; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::StartMouseDrag(nsPresContext* aPresContext, michael@0: nsHTMLFramesetBorderFrame* aBorder, michael@0: WidgetGUIEvent* aEvent) michael@0: { michael@0: #if 0 michael@0: int32_t index; michael@0: IndexOf(aBorder, index); michael@0: NS_ASSERTION((nullptr != aBorder) && (index >= 0), "invalid dragger"); michael@0: #endif michael@0: michael@0: nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED); michael@0: michael@0: mDragger = aBorder; michael@0: michael@0: mFirstDragPoint = LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint); michael@0: michael@0: // Store the original frame sizes michael@0: if (mDragger->mVertical) { michael@0: mPrevNeighborOrigSize = mColSizes[mDragger->mPrevNeighbor]; michael@0: mNextNeighborOrigSize = mColSizes[mDragger->mNextNeighbor]; michael@0: } else { michael@0: mPrevNeighborOrigSize = mRowSizes[mDragger->mPrevNeighbor]; michael@0: mNextNeighborOrigSize = mRowSizes[mDragger->mNextNeighbor]; michael@0: } michael@0: michael@0: gDragInProgress = true; michael@0: } michael@0: michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent) michael@0: { michael@0: // if the capture ended, reset the drag state michael@0: if (nsIPresShell::GetCapturingContent() != GetContent()) { michael@0: mDragger = nullptr; michael@0: gDragInProgress = false; michael@0: return; michael@0: } michael@0: michael@0: int32_t change; // measured positive from left-to-right or top-to-bottom michael@0: nsWeakFrame weakFrame(this); michael@0: if (mDragger->mVertical) { michael@0: change = aPresContext->DevPixelsToAppUnits(aEvent->refPoint.x - mFirstDragPoint.x); michael@0: if (change > mNextNeighborOrigSize - mMinDrag) { michael@0: change = mNextNeighborOrigSize - mMinDrag; michael@0: } else if (change <= mMinDrag - mPrevNeighborOrigSize) { michael@0: change = mMinDrag - mPrevNeighborOrigSize; michael@0: } michael@0: mColSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change; michael@0: mColSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change; michael@0: michael@0: if (change != 0) { michael@0: // Recompute the specs from the new sizes. michael@0: nscoord width = mRect.width - (mNumCols - 1) * GetBorderWidth(aPresContext, true); michael@0: HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent); michael@0: NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!"); michael@0: const nsFramesetSpec* colSpecs = nullptr; michael@0: ourContent->GetColSpec(&mNumCols, &colSpecs); michael@0: nsAutoString newColAttr; michael@0: GenerateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes, michael@0: newColAttr); michael@0: // Setting the attr will trigger a reflow michael@0: mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::cols, newColAttr, true); michael@0: } michael@0: } else { michael@0: change = aPresContext->DevPixelsToAppUnits(aEvent->refPoint.y - mFirstDragPoint.y); michael@0: if (change > mNextNeighborOrigSize - mMinDrag) { michael@0: change = mNextNeighborOrigSize - mMinDrag; michael@0: } else if (change <= mMinDrag - mPrevNeighborOrigSize) { michael@0: change = mMinDrag - mPrevNeighborOrigSize; michael@0: } michael@0: mRowSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change; michael@0: mRowSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change; michael@0: michael@0: if (change != 0) { michael@0: // Recompute the specs from the new sizes. michael@0: nscoord height = mRect.height - (mNumRows - 1) * GetBorderWidth(aPresContext, true); michael@0: HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent); michael@0: NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!"); michael@0: const nsFramesetSpec* rowSpecs = nullptr; michael@0: ourContent->GetRowSpec(&mNumRows, &rowSpecs); michael@0: nsAutoString newRowAttr; michael@0: GenerateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes, michael@0: newRowAttr); michael@0: // Setting the attr will trigger a reflow michael@0: mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::rows, newRowAttr, true); michael@0: } michael@0: } michael@0: michael@0: ENSURE_TRUE(weakFrame.IsAlive()); michael@0: if (change != 0) { michael@0: mDrag.Reset(mDragger->mVertical, mDragger->mPrevNeighbor, change, this); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetFrame::EndMouseDrag(nsPresContext* aPresContext) michael@0: { michael@0: nsIPresShell::SetCapturingContent(nullptr, 0); michael@0: mDragger = nullptr; michael@0: gDragInProgress = false; michael@0: } michael@0: michael@0: nsIFrame* michael@0: NS_NewHTMLFramesetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) michael@0: { michael@0: #ifdef DEBUG michael@0: const nsStyleDisplay* disp = aContext->StyleDisplay(); michael@0: NS_ASSERTION(!disp->IsAbsolutelyPositionedStyle() && !disp->IsFloatingStyle(), michael@0: "Framesets should not be positioned and should not float"); michael@0: #endif michael@0: michael@0: return new (aPresShell) nsHTMLFramesetFrame(aContext); michael@0: } michael@0: michael@0: NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetFrame) michael@0: michael@0: /******************************************************************************* michael@0: * nsHTMLFramesetBorderFrame michael@0: ******************************************************************************/ michael@0: nsHTMLFramesetBorderFrame::nsHTMLFramesetBorderFrame(nsStyleContext* aContext, michael@0: int32_t aWidth, michael@0: bool aVertical, michael@0: bool aVisibility) michael@0: : nsLeafFrame(aContext), mWidth(aWidth), mVertical(aVertical), mVisibility(aVisibility) michael@0: { michael@0: mVisibilityOverride = false; michael@0: mCanResize = true; michael@0: mColor = NO_COLOR; michael@0: mPrevNeighbor = 0; michael@0: mNextNeighbor = 0; michael@0: } michael@0: michael@0: nsHTMLFramesetBorderFrame::~nsHTMLFramesetBorderFrame() michael@0: { michael@0: //printf("nsHTMLFramesetBorderFrame destructor %p \n", this); michael@0: } michael@0: michael@0: NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetBorderFrame) michael@0: michael@0: nscoord nsHTMLFramesetBorderFrame::GetIntrinsicWidth() michael@0: { michael@0: // No intrinsic width michael@0: return 0; michael@0: } michael@0: michael@0: nscoord nsHTMLFramesetBorderFrame::GetIntrinsicHeight() michael@0: { michael@0: // No intrinsic height michael@0: return 0; michael@0: } michael@0: michael@0: void nsHTMLFramesetBorderFrame::SetVisibility(bool aVisibility) michael@0: { michael@0: mVisibility = aVisibility; michael@0: } michael@0: michael@0: void nsHTMLFramesetBorderFrame::SetColor(nscolor aColor) michael@0: { michael@0: mColor = aColor; michael@0: } michael@0: michael@0: michael@0: nsresult michael@0: nsHTMLFramesetBorderFrame::Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) michael@0: { michael@0: DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame"); michael@0: DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); michael@0: michael@0: // Override Reflow(), since we don't want to deal with what our michael@0: // computed values are. michael@0: SizeToAvailSize(aReflowState, aDesiredSize); michael@0: michael@0: aDesiredSize.SetOverflowAreasToDesiredBounds(); michael@0: aStatus = NS_FRAME_COMPLETE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: class nsDisplayFramesetBorder : public nsDisplayItem { michael@0: public: michael@0: nsDisplayFramesetBorder(nsDisplayListBuilder* aBuilder, michael@0: nsHTMLFramesetBorderFrame* aFrame) michael@0: : nsDisplayItem(aBuilder, aFrame) { michael@0: MOZ_COUNT_CTOR(nsDisplayFramesetBorder); michael@0: } michael@0: #ifdef NS_BUILD_REFCNT_LOGGING michael@0: virtual ~nsDisplayFramesetBorder() { michael@0: MOZ_COUNT_DTOR(nsDisplayFramesetBorder); michael@0: } michael@0: #endif michael@0: michael@0: // REVIEW: see old GetFrameForPoint michael@0: // Receives events in its bounds michael@0: virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, michael@0: HitTestState* aState, michael@0: nsTArray *aOutFrames) MOZ_OVERRIDE { michael@0: aOutFrames->AppendElement(mFrame); michael@0: } michael@0: virtual void Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) MOZ_OVERRIDE; michael@0: NS_DISPLAY_DECL_NAME("FramesetBorder", TYPE_FRAMESET_BORDER) michael@0: }; michael@0: michael@0: void nsDisplayFramesetBorder::Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) michael@0: { michael@0: static_cast(mFrame)-> michael@0: PaintBorder(*aCtx, ToReferenceFrame()); michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetBorderFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) michael@0: { michael@0: aLists.Content()->AppendNewToTop( michael@0: new (aBuilder) nsDisplayFramesetBorder(aBuilder, this)); michael@0: } michael@0: michael@0: void nsHTMLFramesetBorderFrame::PaintBorder(nsRenderingContext& aRenderingContext, michael@0: nsPoint aPt) michael@0: { michael@0: nscolor WHITE = NS_RGB(255, 255, 255); michael@0: michael@0: nscolor bgColor = michael@0: LookAndFeel::GetColor(LookAndFeel::eColorID_WidgetBackground, michael@0: NS_RGB(200,200,200)); michael@0: nscolor fgColor = michael@0: LookAndFeel::GetColor(LookAndFeel::eColorID_WidgetForeground, michael@0: NS_RGB(0,0,0)); michael@0: nscolor hltColor = michael@0: LookAndFeel::GetColor(LookAndFeel::eColorID_Widget3DHighlight, michael@0: NS_RGB(255,255,255)); michael@0: nscolor sdwColor = michael@0: LookAndFeel::GetColor(LookAndFeel::eColorID_Widget3DShadow, michael@0: NS_RGB(128,128,128)); michael@0: michael@0: nsRenderingContext::AutoPushTranslation michael@0: translate(&aRenderingContext, aPt); michael@0: michael@0: nscoord widthInPixels = nsPresContext::AppUnitsToIntCSSPixels(mWidth); michael@0: nscoord pixelWidth = nsPresContext::CSSPixelsToAppUnits(1); michael@0: michael@0: if (widthInPixels <= 0) michael@0: return; michael@0: michael@0: nsPoint start(0,0); michael@0: nsPoint end((mVertical) ? 0 : mRect.width, (mVertical) ? mRect.height : 0); michael@0: michael@0: nscolor color = WHITE; michael@0: if (mVisibility || mVisibilityOverride) { michael@0: color = (NO_COLOR == mColor) ? bgColor : mColor; michael@0: } michael@0: aRenderingContext.SetColor(color); michael@0: // draw grey or white first michael@0: for (int i = 0; i < widthInPixels; i++) { michael@0: aRenderingContext.DrawLine (start, end); michael@0: if (mVertical) { michael@0: start.x += pixelWidth; michael@0: end.x = start.x; michael@0: } else { michael@0: start.y += pixelWidth; michael@0: end.y = start.y; michael@0: } michael@0: } michael@0: michael@0: if (!mVisibility && !mVisibilityOverride) michael@0: return; michael@0: michael@0: if (widthInPixels >= 5) { michael@0: aRenderingContext.SetColor(hltColor); michael@0: start.x = (mVertical) ? pixelWidth : 0; michael@0: start.y = (mVertical) ? 0 : pixelWidth; michael@0: end.x = (mVertical) ? start.x : mRect.width; michael@0: end.y = (mVertical) ? mRect.height : start.y; michael@0: aRenderingContext.DrawLine(start, end); michael@0: } michael@0: michael@0: if (widthInPixels >= 2) { michael@0: aRenderingContext.SetColor(sdwColor); michael@0: start.x = (mVertical) ? mRect.width - (2 * pixelWidth) : 0; michael@0: start.y = (mVertical) ? 0 : mRect.height - (2 * pixelWidth); michael@0: end.x = (mVertical) ? start.x : mRect.width; michael@0: end.y = (mVertical) ? mRect.height : start.y; michael@0: aRenderingContext.DrawLine(start, end); michael@0: } michael@0: michael@0: if (widthInPixels >= 1) { michael@0: aRenderingContext.SetColor(fgColor); michael@0: start.x = (mVertical) ? mRect.width - pixelWidth : 0; michael@0: start.y = (mVertical) ? 0 : mRect.height - pixelWidth; michael@0: end.x = (mVertical) ? start.x : mRect.width; michael@0: end.y = (mVertical) ? mRect.height : start.y; michael@0: aRenderingContext.DrawLine(start, end); michael@0: } michael@0: } michael@0: michael@0: michael@0: nsresult michael@0: nsHTMLFramesetBorderFrame::HandleEvent(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aEventStatus); michael@0: *aEventStatus = nsEventStatus_eIgnore; michael@0: michael@0: //XXX Mouse setting logic removed. The remaining logic should also move. michael@0: if (!mCanResize) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (aEvent->message == NS_MOUSE_BUTTON_DOWN && michael@0: aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) { michael@0: nsHTMLFramesetFrame* parentFrame = do_QueryFrame(GetParent()); michael@0: if (parentFrame) { michael@0: parentFrame->StartMouseDrag(aPresContext, this, aEvent); michael@0: *aEventStatus = nsEventStatus_eConsumeNoDefault; michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLFramesetBorderFrame::GetCursor(const nsPoint& aPoint, michael@0: nsIFrame::Cursor& aCursor) michael@0: { michael@0: if (!mCanResize) { michael@0: aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT; michael@0: } else { michael@0: aCursor.mCursor = (mVertical) ? NS_STYLE_CURSOR_EW_RESIZE : NS_STYLE_CURSOR_NS_RESIZE; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: nsresult nsHTMLFramesetBorderFrame::GetFrameName(nsAString& aResult) const michael@0: { michael@0: return MakeFrameName(NS_LITERAL_STRING("FramesetBorder"), aResult); michael@0: } michael@0: #endif michael@0: michael@0: /******************************************************************************* michael@0: * nsHTMLFramesetBlankFrame michael@0: ******************************************************************************/ michael@0: michael@0: NS_QUERYFRAME_HEAD(nsHTMLFramesetBlankFrame) michael@0: NS_QUERYFRAME_ENTRY(nsHTMLFramesetBlankFrame) michael@0: NS_QUERYFRAME_TAIL_INHERITING(nsLeafFrame) michael@0: michael@0: NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetBlankFrame) michael@0: michael@0: nsHTMLFramesetBlankFrame::~nsHTMLFramesetBlankFrame() michael@0: { michael@0: //printf("nsHTMLFramesetBlankFrame destructor %p \n", this); michael@0: } michael@0: michael@0: nscoord nsHTMLFramesetBlankFrame::GetIntrinsicWidth() michael@0: { michael@0: // No intrinsic width michael@0: return 0; michael@0: } michael@0: michael@0: nscoord nsHTMLFramesetBlankFrame::GetIntrinsicHeight() michael@0: { michael@0: // No intrinsic height michael@0: return 0; michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLFramesetBlankFrame::Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) michael@0: { michael@0: DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame"); michael@0: michael@0: // Override Reflow(), since we don't want to deal with what our michael@0: // computed values are. michael@0: SizeToAvailSize(aReflowState, aDesiredSize); michael@0: michael@0: aDesiredSize.SetOverflowAreasToDesiredBounds(); michael@0: aStatus = NS_FRAME_COMPLETE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: class nsDisplayFramesetBlank : public nsDisplayItem { michael@0: public: michael@0: nsDisplayFramesetBlank(nsDisplayListBuilder* aBuilder, michael@0: nsIFrame* aFrame) : michael@0: nsDisplayItem(aBuilder, aFrame) { michael@0: MOZ_COUNT_CTOR(nsDisplayFramesetBlank); michael@0: } michael@0: #ifdef NS_BUILD_REFCNT_LOGGING michael@0: virtual ~nsDisplayFramesetBlank() { michael@0: MOZ_COUNT_DTOR(nsDisplayFramesetBlank); michael@0: } michael@0: #endif michael@0: michael@0: virtual void Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) MOZ_OVERRIDE; michael@0: NS_DISPLAY_DECL_NAME("FramesetBlank", TYPE_FRAMESET_BLANK) michael@0: }; michael@0: michael@0: void nsDisplayFramesetBlank::Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) michael@0: { michael@0: nscolor white = NS_RGB(255,255,255); michael@0: aCtx->SetColor(white); michael@0: aCtx->FillRect(mVisibleRect); michael@0: } michael@0: michael@0: void michael@0: nsHTMLFramesetBlankFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) michael@0: { michael@0: aLists.Content()->AppendNewToTop( michael@0: new (aBuilder) nsDisplayFramesetBlank(aBuilder, this)); michael@0: }