1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 /* rendering object for HTML <frameset> elements */
8
9 #include "nsFrameSetFrame.h"
10
11 #include "gfxContext.h"
12 #include "gfxUtils.h"
13 #include "mozilla/DebugOnly.h"
14 #include "mozilla/gfx/2D.h"
15 #include "mozilla/gfx/Helpers.h"
16 #include "mozilla/Likely.h"
17
18 #include "nsGenericHTMLElement.h"
19 #include "nsAttrValueInlines.h"
20 #include "nsLeafFrame.h"
21 #include "nsContainerFrame.h"
22 #include "nsLayoutUtils.h"
23 #include "nsPresContext.h"
24 #include "nsIContentInlines.h"
25 #include "nsIPresShell.h"
26 #include "nsGkAtoms.h"
27 #include "nsStyleConsts.h"
28 #include "nsStyleContext.h"
29 #include "nsHTMLParts.h"
30 #include "nsNameSpaceManager.h"
31 #include "nsCSSAnonBoxes.h"
32 #include "mozilla/StyleSetHandle.h"
33 #include "mozilla/StyleSetHandleInlines.h"
34 #include "mozilla/dom/Element.h"
35 #include "nsDisplayList.h"
36 #include "nsNodeUtils.h"
37 #include "mozAutoDocUpdate.h"
38 #include "mozilla/Preferences.h"
39 #include "mozilla/dom/HTMLFrameSetElement.h"
40 #include "mozilla/LookAndFeel.h"
41 #include "mozilla/MouseEvents.h"
42 #include "nsSubDocumentFrame.h"
43
44 using namespace mozilla;
45 using namespace mozilla::dom;
46 using namespace mozilla::gfx;
47
48 // masks for mEdgeVisibility
49 #define LEFT_VIS 0x0001
50 #define RIGHT_VIS 0x0002
51 #define TOP_VIS 0x0004
52 #define BOTTOM_VIS 0x0008
53 #define ALL_VIS 0x000F
54 #define NONE_VIS 0x0000
55
56 /*******************************************************************************
57 * nsFramesetDrag
58 ******************************************************************************/
nsFramesetDrag()59 nsFramesetDrag::nsFramesetDrag() { UnSet(); }
60
Reset(bool aVertical,int32_t aIndex,int32_t aChange,nsHTMLFramesetFrame * aSource)61 void nsFramesetDrag::Reset(bool aVertical, int32_t aIndex, int32_t aChange,
62 nsHTMLFramesetFrame* aSource) {
63 mVertical = aVertical;
64 mIndex = aIndex;
65 mChange = aChange;
66 mSource = aSource;
67 }
68
UnSet()69 void nsFramesetDrag::UnSet() {
70 mVertical = true;
71 mIndex = -1;
72 mChange = 0;
73 mSource = nullptr;
74 }
75
76 /*******************************************************************************
77 * nsHTMLFramesetBorderFrame
78 ******************************************************************************/
79 class nsHTMLFramesetBorderFrame final : public nsLeafFrame {
80 public:
81 NS_DECL_FRAMEARENA_HELPERS(nsHTMLFramesetBorderFrame)
82
83 #ifdef DEBUG_FRAME_DUMP
84 virtual nsresult GetFrameName(nsAString& aResult) const override;
85 #endif
86
87 virtual nsresult HandleEvent(nsPresContext* aPresContext,
88 WidgetGUIEvent* aEvent,
89 nsEventStatus* aEventStatus) override;
90
91 virtual nsresult GetCursor(const nsPoint& aPoint,
92 nsIFrame::Cursor& aCursor) override;
93
94 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
95 const nsDisplayListSet& aLists) override;
96
97 virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
98 const ReflowInput& aReflowInput,
99 nsReflowStatus& aStatus) override;
100
GetVisibility()101 bool GetVisibility() { return mVisibility; }
102 void SetVisibility(bool aVisibility);
103 void SetColor(nscolor aColor);
104
105 void PaintBorder(DrawTarget* aDrawTarget, nsPoint aPt);
106
107 protected:
108 nsHTMLFramesetBorderFrame(nsStyleContext* aContext, int32_t aWidth,
109 bool aVertical, bool aVisible);
110 virtual ~nsHTMLFramesetBorderFrame();
111 virtual nscoord GetIntrinsicISize() override;
112 virtual nscoord GetIntrinsicBSize() override;
113
114 // the prev and next neighbors are indexes into the row (for a horizontal
115 // border) or col (for a vertical border) of nsHTMLFramesetFrames or
116 // nsHTMLFrames
117 int32_t mPrevNeighbor;
118 int32_t mNextNeighbor;
119 nscolor mColor;
120 int32_t mWidth;
121 bool mVertical;
122 bool mVisibility;
123 bool mCanResize;
124 friend class nsHTMLFramesetFrame;
125 };
126 /*******************************************************************************
127 * nsHTMLFramesetBlankFrame
128 ******************************************************************************/
129 class nsHTMLFramesetBlankFrame final : public nsLeafFrame {
130 public:
131 NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsHTMLFramesetBlankFrame)132 NS_DECL_FRAMEARENA_HELPERS(nsHTMLFramesetBlankFrame)
133
134 #ifdef DEBUG_FRAME_DUMP
135 virtual nsresult GetFrameName(nsAString& aResult) const override {
136 return MakeFrameName(NS_LITERAL_STRING("FramesetBlank"), aResult);
137 }
138 #endif
139
140 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
141 const nsDisplayListSet& aLists) override;
142
143 virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
144 const ReflowInput& aReflowInput,
145 nsReflowStatus& aStatus) override;
146
147 protected:
nsHTMLFramesetBlankFrame(nsStyleContext * aContext)148 explicit nsHTMLFramesetBlankFrame(nsStyleContext* aContext)
149 : nsLeafFrame(aContext, kClassID) {}
150
151 virtual ~nsHTMLFramesetBlankFrame();
152 virtual nscoord GetIntrinsicISize() override;
153 virtual nscoord GetIntrinsicBSize() override;
154
155 friend class nsHTMLFramesetFrame;
156 friend class nsHTMLFrameset;
157 };
158
159 /*******************************************************************************
160 * nsHTMLFramesetFrame
161 ******************************************************************************/
162 bool nsHTMLFramesetFrame::gDragInProgress = false;
163 #define DEFAULT_BORDER_WIDTH_PX 6
164
nsHTMLFramesetFrame(nsStyleContext * aContext)165 nsHTMLFramesetFrame::nsHTMLFramesetFrame(nsStyleContext* aContext)
166 : nsContainerFrame(aContext, kClassID) {
167 mNumRows = 0;
168 mNumCols = 0;
169 mEdgeVisibility = 0;
170 mParentFrameborder = eFrameborder_Yes; // default
171 mParentBorderWidth = -1; // default not set
172 mParentBorderColor = NO_COLOR; // default not set
173 mFirstDragPoint.x = mFirstDragPoint.y = 0;
174 mMinDrag = nsPresContext::CSSPixelsToAppUnits(2);
175 mNonBorderChildCount = 0;
176 mNonBlankChildCount = 0;
177 mDragger = nullptr;
178 mChildCount = 0;
179 mTopLevelFrameset = nullptr;
180 mEdgeColors.Set(NO_COLOR);
181 }
182
~nsHTMLFramesetFrame()183 nsHTMLFramesetFrame::~nsHTMLFramesetFrame() {}
184
185 NS_QUERYFRAME_HEAD(nsHTMLFramesetFrame)
NS_QUERYFRAME_ENTRY(nsHTMLFramesetFrame)186 NS_QUERYFRAME_ENTRY(nsHTMLFramesetFrame)
187 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
188
189 void nsHTMLFramesetFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
190 nsIFrame* aPrevInFlow) {
191 nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
192 // find the highest ancestor that is a frameset
193 nsIFrame* parentFrame = GetParent();
194 mTopLevelFrameset = this;
195 while (parentFrame) {
196 nsHTMLFramesetFrame* frameset = do_QueryFrame(parentFrame);
197 if (frameset) {
198 mTopLevelFrameset = frameset;
199 parentFrame = parentFrame->GetParent();
200 } else {
201 break;
202 }
203 }
204
205 nsPresContext* presContext = PresContext();
206 nsIPresShell* shell = presContext->PresShell();
207
208 nsFrameborder frameborder = GetFrameBorder();
209 int32_t borderWidth = GetBorderWidth(presContext, false);
210 nscolor borderColor = GetBorderColor();
211
212 // Get the rows= cols= data
213 HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent);
214 NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
215 const nsFramesetSpec* rowSpecs = nullptr;
216 const nsFramesetSpec* colSpecs = nullptr;
217 // GetRowSpec and GetColSpec can fail, but when they do they set
218 // mNumRows and mNumCols respectively to 0, so we deal with it fine.
219 ourContent->GetRowSpec(&mNumRows, &rowSpecs);
220 ourContent->GetColSpec(&mNumCols, &colSpecs);
221
222 static_assert(
223 NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscoord),
224 "Maximum value of mNumRows and mNumCols is NS_MAX_FRAMESET_SPEC_COUNT");
225 mRowSizes = MakeUnique<nscoord[]>(mNumRows);
226 mColSizes = MakeUnique<nscoord[]>(mNumCols);
227
228 static_assert(
229 NS_MAX_FRAMESET_SPEC_COUNT < INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT,
230 "Should not overflow numCells");
231 int32_t numCells = mNumRows * mNumCols;
232
233 static_assert(NS_MAX_FRAMESET_SPEC_COUNT <
234 UINT_MAX / sizeof(nsHTMLFramesetBorderFrame*),
235 "Should not overflow nsHTMLFramesetBorderFrame");
236 mVerBorders = MakeUnique<nsHTMLFramesetBorderFrame* []>(
237 mNumCols); // 1 more than number of ver borders
238
239 for (int verX = 0; verX < mNumCols; verX++) mVerBorders[verX] = nullptr;
240
241 mHorBorders = MakeUnique<nsHTMLFramesetBorderFrame* []>(
242 mNumRows); // 1 more than number of hor borders
243
244 for (int horX = 0; horX < mNumRows; horX++) mHorBorders[horX] = nullptr;
245
246 static_assert(NS_MAX_FRAMESET_SPEC_COUNT <
247 UINT_MAX / sizeof(int32_t) / NS_MAX_FRAMESET_SPEC_COUNT,
248 "Should not overflow numCells");
249 static_assert(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nsFrameborder) /
250 NS_MAX_FRAMESET_SPEC_COUNT,
251 "Should not overflow numCells");
252 static_assert(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nsBorderColor) /
253 NS_MAX_FRAMESET_SPEC_COUNT,
254 "Should not overflow numCells");
255 mChildFrameborder = MakeUnique<nsFrameborder[]>(numCells);
256 mChildBorderColors = MakeUnique<nsBorderColor[]>(numCells);
257
258 // create the children frames; skip content which isn't <frameset> or <frame>
259 mChildCount = 0; // number of <frame> or <frameset> children
260
261 for (nsIContent* child = mContent->GetFirstChild(); child;
262 child = child->GetNextSibling()) {
263 if (mChildCount ==
264 numCells) { // we have more <frame> or <frameset> than cells
265 // Clear the lazy bits in the remaining children. Also clear
266 // the restyle flags, like nsCSSFrameConstructor::ProcessChildren does.
267 for (; child; child = child->GetNextSibling()) {
268 child->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
269 child->UnsetRestyleFlagsIfGecko();
270 }
271 break;
272 }
273 child->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
274 // Also clear the restyle flags in the child like
275 // nsCSSFrameConstructor::ProcessChildren does.
276 child->UnsetRestyleFlagsIfGecko();
277
278 // IMPORTANT: This must match the conditions in
279 // nsCSSFrameConstructor::ContentAppended/Inserted/Removed
280 if (!child->IsHTMLElement()) {
281 continue;
282 }
283
284 if (!child->IsAnyOfHTMLElements(nsGkAtoms::frameset, nsGkAtoms::frame)) {
285 continue;
286 }
287
288 RefPtr<nsStyleContext> kidSC = shell->StyleSet()->ResolveStyleFor(
289 child->AsElement(), mStyleContext, LazyComputeBehavior::Allow);
290
291 nsIFrame* frame;
292 if (child->IsHTMLElement(nsGkAtoms::frameset)) {
293 frame = NS_NewHTMLFramesetFrame(shell, kidSC);
294
295 nsHTMLFramesetFrame* childFrame = (nsHTMLFramesetFrame*)frame;
296 childFrame->SetParentFrameborder(frameborder);
297 childFrame->SetParentBorderWidth(borderWidth);
298 childFrame->SetParentBorderColor(borderColor);
299 frame->Init(child, this, nullptr);
300
301 mChildBorderColors[mChildCount].Set(childFrame->GetBorderColor());
302 } else { // frame
303 frame = NS_NewSubDocumentFrame(shell, kidSC);
304
305 frame->Init(child, this, nullptr);
306
307 mChildFrameborder[mChildCount] = GetFrameBorder(child);
308 mChildBorderColors[mChildCount].Set(GetBorderColor(child));
309 }
310 child->SetPrimaryFrame(frame);
311
312 mFrames.AppendFrame(nullptr, frame);
313
314 mChildCount++;
315 }
316
317 mNonBlankChildCount = mChildCount;
318 // add blank frames for frameset cells that had no content provided
319 for (int blankX = mChildCount; blankX < numCells; blankX++) {
320 RefPtr<nsStyleContext> pseudoStyleContext;
321 pseudoStyleContext =
322 shell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
323 nsCSSAnonBoxes::framesetBlank);
324
325 // XXX the blank frame is using the content of its parent - at some point it
326 // should just have null content, if we support that
327 nsHTMLFramesetBlankFrame* blankFrame =
328 new (shell) nsHTMLFramesetBlankFrame(pseudoStyleContext);
329
330 blankFrame->Init(mContent, this, nullptr);
331
332 mFrames.AppendFrame(nullptr, blankFrame);
333
334 mChildBorderColors[mChildCount].Set(NO_COLOR);
335 mChildCount++;
336 }
337
338 mNonBorderChildCount = mChildCount;
339 }
340
SetInitialChildList(ChildListID aListID,nsFrameList & aChildList)341 void nsHTMLFramesetFrame::SetInitialChildList(ChildListID aListID,
342 nsFrameList& aChildList) {
343 // We do this weirdness where we create our child frames in Init(). On the
344 // other hand, we're going to get a SetInitialChildList() with an empty list
345 // and null list name after the frame constructor is done creating us. So
346 // just ignore that call.
347 if (aListID == kPrincipalList && aChildList.IsEmpty()) {
348 return;
349 }
350
351 nsContainerFrame::SetInitialChildList(aListID, aChildList);
352 }
353
354 // XXX should this try to allocate twips based on an even pixel boundary?
Scale(nscoord aDesired,int32_t aNumIndicies,int32_t * aIndicies,int32_t aNumItems,int32_t * aItems)355 void nsHTMLFramesetFrame::Scale(nscoord aDesired, int32_t aNumIndicies,
356 int32_t* aIndicies, int32_t aNumItems,
357 int32_t* aItems) {
358 int32_t actual = 0;
359 int32_t i, j;
360 // get the actual total
361 for (i = 0; i < aNumIndicies; i++) {
362 j = aIndicies[i];
363 actual += aItems[j];
364 }
365
366 if (actual > 0) {
367 float factor = (float)aDesired / (float)actual;
368 actual = 0;
369 // scale the items up or down
370 for (i = 0; i < aNumIndicies; i++) {
371 j = aIndicies[i];
372 aItems[j] = NSToCoordRound((float)aItems[j] * factor);
373 actual += aItems[j];
374 }
375 } else if (aNumIndicies != 0) {
376 // All the specs say zero width, but we have to fill up space
377 // somehow. Distribute it equally.
378 nscoord width = NSToCoordRound((float)aDesired / (float)aNumIndicies);
379 actual = width * aNumIndicies;
380 for (i = 0; i < aNumIndicies; i++) {
381 aItems[aIndicies[i]] = width;
382 }
383 }
384
385 if (aNumIndicies > 0 && aDesired != actual) {
386 int32_t unit = (aDesired > actual) ? 1 : -1;
387 for (i = 0; (i < aNumIndicies) && (aDesired != actual); i++) {
388 j = aIndicies[i];
389 if (j < aNumItems) {
390 aItems[j] += unit;
391 actual += unit;
392 }
393 }
394 }
395 }
396
397 /**
398 * Translate the rows/cols specs into an array of integer sizes for
399 * each cell in the frameset. Sizes are allocated based on the priorities of the
400 * specifier - fixed sizes have the highest priority, percentage sizes have the
401 * next highest priority and relative sizes have the lowest.
402 */
CalculateRowCol(nsPresContext * aPresContext,nscoord aSize,int32_t aNumSpecs,const nsFramesetSpec * aSpecs,nscoord * aValues)403 void nsHTMLFramesetFrame::CalculateRowCol(nsPresContext* aPresContext,
404 nscoord aSize, int32_t aNumSpecs,
405 const nsFramesetSpec* aSpecs,
406 nscoord* aValues) {
407 static_assert(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(int32_t),
408 "aNumSpecs maximum value is NS_MAX_FRAMESET_SPEC_COUNT");
409
410 int32_t fixedTotal = 0;
411 int32_t numFixed = 0;
412 auto fixed = MakeUnique<int32_t[]>(aNumSpecs);
413 int32_t numPercent = 0;
414 auto percent = MakeUnique<int32_t[]>(aNumSpecs);
415 int32_t relativeSums = 0;
416 int32_t numRelative = 0;
417 auto relative = MakeUnique<int32_t[]>(aNumSpecs);
418
419 if (MOZ_UNLIKELY(!fixed || !percent || !relative)) {
420 return; // NS_ERROR_OUT_OF_MEMORY
421 }
422
423 int32_t i, j;
424
425 // initialize the fixed, percent, relative indices, allocate the fixed sizes
426 // and zero the others
427 for (i = 0; i < aNumSpecs; i++) {
428 aValues[i] = 0;
429 switch (aSpecs[i].mUnit) {
430 case eFramesetUnit_Fixed:
431 aValues[i] = nsPresContext::CSSPixelsToAppUnits(aSpecs[i].mValue);
432 fixedTotal += aValues[i];
433 fixed[numFixed] = i;
434 numFixed++;
435 break;
436 case eFramesetUnit_Percent:
437 percent[numPercent] = i;
438 numPercent++;
439 break;
440 case eFramesetUnit_Relative:
441 relative[numRelative] = i;
442 numRelative++;
443 relativeSums += aSpecs[i].mValue;
444 break;
445 }
446 }
447
448 // scale the fixed sizes if they total too much (or too little and there
449 // aren't any percent or relative)
450 if ((fixedTotal > aSize) ||
451 ((fixedTotal < aSize) && (0 == numPercent) && (0 == numRelative))) {
452 Scale(aSize, numFixed, fixed.get(), aNumSpecs, aValues);
453 return;
454 }
455
456 int32_t percentMax = aSize - fixedTotal;
457 int32_t percentTotal = 0;
458 // allocate the percentage sizes from what is left over from the fixed
459 // allocation
460 for (i = 0; i < numPercent; i++) {
461 j = percent[i];
462 aValues[j] =
463 NSToCoordRound((float)aSpecs[j].mValue * (float)aSize / 100.0f);
464 percentTotal += aValues[j];
465 }
466
467 // scale the percent sizes if they total too much (or too little and there
468 // aren't any relative)
469 if ((percentTotal > percentMax) ||
470 ((percentTotal < percentMax) && (0 == numRelative))) {
471 Scale(percentMax, numPercent, percent.get(), aNumSpecs, aValues);
472 return;
473 }
474
475 int32_t relativeMax = percentMax - percentTotal;
476 int32_t relativeTotal = 0;
477 // allocate the relative sizes from what is left over from the percent
478 // allocation
479 for (i = 0; i < numRelative; i++) {
480 j = relative[i];
481 aValues[j] = NSToCoordRound((float)aSpecs[j].mValue * (float)relativeMax /
482 (float)relativeSums);
483 relativeTotal += aValues[j];
484 }
485
486 // scale the relative sizes if they take up too much or too little
487 if (relativeTotal != relativeMax) {
488 Scale(relativeMax, numRelative, relative.get(), aNumSpecs, aValues);
489 }
490 }
491
492 /**
493 * Translate the rows/cols integer sizes into an array of specs for
494 * each cell in the frameset. Reverse of CalculateRowCol() behaviour.
495 * This allows us to maintain the user size info through reflows.
496 */
GenerateRowCol(nsPresContext * aPresContext,nscoord aSize,int32_t aNumSpecs,const nsFramesetSpec * aSpecs,nscoord * aValues,nsString & aNewAttr)497 void nsHTMLFramesetFrame::GenerateRowCol(nsPresContext* aPresContext,
498 nscoord aSize, int32_t aNumSpecs,
499 const nsFramesetSpec* aSpecs,
500 nscoord* aValues, nsString& aNewAttr) {
501 int32_t i;
502
503 for (i = 0; i < aNumSpecs; i++) {
504 if (!aNewAttr.IsEmpty()) aNewAttr.Append(char16_t(','));
505
506 switch (aSpecs[i].mUnit) {
507 case eFramesetUnit_Fixed:
508 aNewAttr.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(aValues[i]));
509 break;
510 case eFramesetUnit_Percent: // XXX Only accurate to 1%, need 1 pixel
511 case eFramesetUnit_Relative:
512 // Add 0.5 to the percentage to make rounding work right.
513 aNewAttr.AppendInt(uint32_t((100.0 * aValues[i]) / aSize + 0.5));
514 aNewAttr.Append(char16_t('%'));
515 break;
516 }
517 }
518 }
519
GetBorderWidth(nsPresContext * aPresContext,bool aTakeForcingIntoAccount)520 int32_t nsHTMLFramesetFrame::GetBorderWidth(nsPresContext* aPresContext,
521 bool aTakeForcingIntoAccount) {
522 nsFrameborder frameborder = GetFrameBorder();
523 if (frameborder == eFrameborder_No) {
524 return 0;
525 }
526 nsGenericHTMLElement* content = nsGenericHTMLElement::FromContent(mContent);
527
528 if (content) {
529 const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::border);
530 if (attr) {
531 int32_t intVal = 0;
532 if (attr->Type() == nsAttrValue::eInteger) {
533 intVal = attr->GetIntegerValue();
534 if (intVal < 0) {
535 intVal = 0;
536 }
537 }
538
539 return nsPresContext::CSSPixelsToAppUnits(intVal);
540 }
541 }
542
543 if (mParentBorderWidth >= 0) {
544 return mParentBorderWidth;
545 }
546
547 return nsPresContext::CSSPixelsToAppUnits(DEFAULT_BORDER_WIDTH_PX);
548 }
549
GetDesiredSize(nsPresContext * aPresContext,const ReflowInput & aReflowInput,ReflowOutput & aDesiredSize)550 void nsHTMLFramesetFrame::GetDesiredSize(nsPresContext* aPresContext,
551 const ReflowInput& aReflowInput,
552 ReflowOutput& aDesiredSize) {
553 WritingMode wm = aReflowInput.GetWritingMode();
554 LogicalSize desiredSize(wm);
555 nsHTMLFramesetFrame* framesetParent = do_QueryFrame(GetParent());
556 if (nullptr == framesetParent) {
557 if (aPresContext->IsPaginated()) {
558 // XXX This needs to be changed when framesets paginate properly
559 desiredSize.ISize(wm) = aReflowInput.AvailableISize();
560 desiredSize.BSize(wm) = aReflowInput.AvailableBSize();
561 } else {
562 LogicalSize area(wm, aPresContext->GetVisibleArea().Size());
563
564 desiredSize.ISize(wm) = area.ISize(wm);
565 desiredSize.BSize(wm) = area.BSize(wm);
566 }
567 } else {
568 LogicalSize size(wm);
569 framesetParent->GetSizeOfChild(this, wm, size);
570 desiredSize.ISize(wm) = size.ISize(wm);
571 desiredSize.BSize(wm) = size.BSize(wm);
572 }
573 aDesiredSize.SetSize(wm, desiredSize);
574 }
575
576 // only valid for non border children
GetSizeOfChildAt(int32_t aIndexInParent,WritingMode aWM,LogicalSize & aSize,nsIntPoint & aCellIndex)577 void nsHTMLFramesetFrame::GetSizeOfChildAt(int32_t aIndexInParent,
578 WritingMode aWM, LogicalSize& aSize,
579 nsIntPoint& aCellIndex) {
580 int32_t row = aIndexInParent / mNumCols;
581 int32_t col = aIndexInParent -
582 (row * mNumCols); // remainder from dividing index by mNumCols
583 if ((row < mNumRows) && (col < mNumCols)) {
584 aSize.ISize(aWM) = mColSizes[col];
585 aSize.BSize(aWM) = mRowSizes[row];
586 aCellIndex.x = col;
587 aCellIndex.y = row;
588 } else {
589 aSize.SizeTo(aWM, 0, 0);
590 aCellIndex.x = aCellIndex.y = 0;
591 }
592 }
593
594 // only valid for non border children
GetSizeOfChild(nsIFrame * aChild,WritingMode aWM,LogicalSize & aSize)595 void nsHTMLFramesetFrame::GetSizeOfChild(nsIFrame* aChild, WritingMode aWM,
596 LogicalSize& aSize) {
597 // Reflow only creates children frames for <frameset> and <frame> content.
598 // this assumption is used here
599 int i = 0;
600 for (nsIFrame* child : mFrames) {
601 if (aChild == child) {
602 nsIntPoint ignore;
603 GetSizeOfChildAt(i, aWM, aSize, ignore);
604 return;
605 }
606 i++;
607 }
608 aSize.SizeTo(aWM, 0, 0);
609 }
610
HandleEvent(nsPresContext * aPresContext,WidgetGUIEvent * aEvent,nsEventStatus * aEventStatus)611 nsresult nsHTMLFramesetFrame::HandleEvent(nsPresContext* aPresContext,
612 WidgetGUIEvent* aEvent,
613 nsEventStatus* aEventStatus) {
614 NS_ENSURE_ARG_POINTER(aEventStatus);
615 if (mDragger) {
616 // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
617 switch (aEvent->mMessage) {
618 case eMouseMove:
619 MouseDrag(aPresContext, aEvent);
620 break;
621 case eMouseUp:
622 if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
623 EndMouseDrag(aPresContext);
624 }
625 break;
626 default:
627 break;
628 }
629 *aEventStatus = nsEventStatus_eConsumeNoDefault;
630 } else {
631 *aEventStatus = nsEventStatus_eIgnore;
632 }
633 return NS_OK;
634 }
635
GetCursor(const nsPoint & aPoint,nsIFrame::Cursor & aCursor)636 nsresult nsHTMLFramesetFrame::GetCursor(const nsPoint& aPoint,
637 nsIFrame::Cursor& aCursor) {
638 aCursor.mLoading = false;
639 if (mDragger) {
640 aCursor.mCursor = (mDragger->mVertical) ? NS_STYLE_CURSOR_EW_RESIZE
641 : NS_STYLE_CURSOR_NS_RESIZE;
642 } else {
643 aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
644 }
645 return NS_OK;
646 }
647
BuildDisplayList(nsDisplayListBuilder * aBuilder,const nsDisplayListSet & aLists)648 void nsHTMLFramesetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
649 const nsDisplayListSet& aLists) {
650 BuildDisplayListForInline(aBuilder, aLists);
651
652 if (mDragger && aBuilder->IsForEventDelivery()) {
653 aLists.Content()->AppendToTop(
654 MakeDisplayItem<nsDisplayEventReceiver>(aBuilder, this));
655 }
656 }
657
ReflowPlaceChild(nsIFrame * aChild,nsPresContext * aPresContext,const ReflowInput & aReflowInput,nsPoint & aOffset,nsSize & aSize,nsIntPoint * aCellIndex)658 void nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame* aChild,
659 nsPresContext* aPresContext,
660 const ReflowInput& aReflowInput,
661 nsPoint& aOffset, nsSize& aSize,
662 nsIntPoint* aCellIndex) {
663 // reflow the child
664 ReflowInput reflowInput(aPresContext, aReflowInput, aChild,
665 LogicalSize(aChild->GetWritingMode(), aSize));
666 reflowInput.SetComputedWidth(std::max(
667 0,
668 aSize.width - reflowInput.ComputedPhysicalBorderPadding().LeftRight()));
669 reflowInput.SetComputedHeight(std::max(
670 0,
671 aSize.height - reflowInput.ComputedPhysicalBorderPadding().TopBottom()));
672 ReflowOutput reflowOutput(aReflowInput);
673 reflowOutput.Width() = aSize.width;
674 reflowOutput.Height() = aSize.height;
675 nsReflowStatus status;
676
677 ReflowChild(aChild, aPresContext, reflowOutput, reflowInput, aOffset.x,
678 aOffset.y, 0, status);
679 NS_ASSERTION(status.IsComplete(), "bad status");
680
681 // Place and size the child
682 reflowOutput.Width() = aSize.width;
683 reflowOutput.Height() = aSize.height;
684 FinishReflowChild(aChild, aPresContext, reflowOutput, nullptr, aOffset.x,
685 aOffset.y, 0);
686 }
687
GetFrameBorderHelper(nsGenericHTMLElement * aContent)688 static nsFrameborder GetFrameBorderHelper(nsGenericHTMLElement* aContent) {
689 if (nullptr != aContent) {
690 const nsAttrValue* attr = aContent->GetParsedAttr(nsGkAtoms::frameborder);
691 if (attr && attr->Type() == nsAttrValue::eEnum) {
692 switch (attr->GetEnumValue()) {
693 case NS_STYLE_FRAME_YES:
694 case NS_STYLE_FRAME_1:
695 return eFrameborder_Yes;
696
697 case NS_STYLE_FRAME_NO:
698 case NS_STYLE_FRAME_0:
699 return eFrameborder_No;
700 }
701 }
702 }
703 return eFrameborder_Notset;
704 }
705
GetFrameBorder()706 nsFrameborder nsHTMLFramesetFrame::GetFrameBorder() {
707 nsFrameborder result = eFrameborder_Notset;
708 nsGenericHTMLElement* content = nsGenericHTMLElement::FromContent(mContent);
709
710 if (content) {
711 result = GetFrameBorderHelper(content);
712 }
713 if (eFrameborder_Notset == result) {
714 return mParentFrameborder;
715 }
716 return result;
717 }
718
GetFrameBorder(nsIContent * aContent)719 nsFrameborder nsHTMLFramesetFrame::GetFrameBorder(nsIContent* aContent) {
720 nsFrameborder result = eFrameborder_Notset;
721
722 nsGenericHTMLElement* content = nsGenericHTMLElement::FromContent(aContent);
723
724 if (content) {
725 result = GetFrameBorderHelper(content);
726 }
727 if (eFrameborder_Notset == result) {
728 return GetFrameBorder();
729 }
730 return result;
731 }
732
GetBorderColor()733 nscolor nsHTMLFramesetFrame::GetBorderColor() {
734 nsGenericHTMLElement* content = nsGenericHTMLElement::FromContent(mContent);
735
736 if (content) {
737 const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::bordercolor);
738 if (attr) {
739 nscolor color;
740 if (attr->GetColorValue(color)) {
741 return color;
742 }
743 }
744 }
745
746 return mParentBorderColor;
747 }
748
GetBorderColor(nsIContent * aContent)749 nscolor nsHTMLFramesetFrame::GetBorderColor(nsIContent* aContent) {
750 nsGenericHTMLElement* content = nsGenericHTMLElement::FromContent(aContent);
751
752 if (content) {
753 const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::bordercolor);
754 if (attr) {
755 nscolor color;
756 if (attr->GetColorValue(color)) {
757 return color;
758 }
759 }
760 }
761 return GetBorderColor();
762 }
763
Reflow(nsPresContext * aPresContext,ReflowOutput & aDesiredSize,const ReflowInput & aReflowInput,nsReflowStatus & aStatus)764 void nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
765 ReflowOutput& aDesiredSize,
766 const ReflowInput& aReflowInput,
767 nsReflowStatus& aStatus) {
768 MarkInReflow();
769 DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame");
770 DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
771 MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
772
773 nsIPresShell* shell = aPresContext->PresShell();
774 StyleSetHandle styleSet = shell->StyleSet();
775
776 GetParent()->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
777
778 // printf("FramesetFrame2::Reflow %X (%d,%d) \n", this,
779 // aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight());
780 // Always get the size so that the caller knows how big we are
781 GetDesiredSize(aPresContext, aReflowInput, aDesiredSize);
782
783 nscoord width = (aDesiredSize.Width() <= aReflowInput.AvailableWidth())
784 ? aDesiredSize.Width()
785 : aReflowInput.AvailableWidth();
786 nscoord height = (aDesiredSize.Height() <= aReflowInput.AvailableHeight())
787 ? aDesiredSize.Height()
788 : aReflowInput.AvailableHeight();
789
790 // We might be reflowed more than once with NS_FRAME_FIRST_REFLOW;
791 // that's allowed. (Though it will only happen for misuse of frameset
792 // that includes it within other content.) So measure firstTime by
793 // what we care about, which is whether we've processed the data we
794 // process below if firstTime is true.
795 MOZ_ASSERT(!mChildFrameborder == !mChildBorderColors);
796 bool firstTime = !!mChildFrameborder;
797
798 // subtract out the width of all of the potential borders. There are
799 // only borders between <frame>s. There are none on the edges (e.g the
800 // leftmost <frame> has no left border).
801 int32_t borderWidth = GetBorderWidth(aPresContext, true);
802
803 width -= (mNumCols - 1) * borderWidth;
804 if (width < 0) width = 0;
805
806 height -= (mNumRows - 1) * borderWidth;
807 if (height < 0) height = 0;
808
809 HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent);
810 NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
811 const nsFramesetSpec* rowSpecs = nullptr;
812 const nsFramesetSpec* colSpecs = nullptr;
813 int32_t rows = 0;
814 int32_t cols = 0;
815 ourContent->GetRowSpec(&rows, &rowSpecs);
816 ourContent->GetColSpec(&cols, &colSpecs);
817 // If the number of cols or rows has changed, the frame for the frameset
818 // will be re-created.
819 if (mNumRows != rows || mNumCols != cols) {
820 mDrag.UnSet();
821 NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
822 return;
823 }
824
825 CalculateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes.get());
826 CalculateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes.get());
827
828 UniquePtr<bool[]> verBordersVis; // vertical borders visibility
829 UniquePtr<nscolor[]> verBorderColors;
830 UniquePtr<bool[]> horBordersVis; // horizontal borders visibility
831 UniquePtr<nscolor[]> horBorderColors;
832 nscolor borderColor = GetBorderColor();
833 nsFrameborder frameborder = GetFrameBorder();
834
835 if (firstTime) {
836 // Check for overflow in memory allocations using mNumCols and mNumRows
837 // which have a maxium value of NS_MAX_FRAMESET_SPEC_COUNT.
838 static_assert(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(bool),
839 "Check for overflow");
840 static_assert(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscolor),
841 "Check for overflow");
842
843 verBordersVis = MakeUnique<bool[]>(mNumCols);
844 verBorderColors = MakeUnique<nscolor[]>(mNumCols);
845 for (int verX = 0; verX < mNumCols; verX++) {
846 verBordersVis[verX] = false;
847 verBorderColors[verX] = NO_COLOR;
848 }
849
850 horBordersVis = MakeUnique<bool[]>(mNumRows);
851 horBorderColors = MakeUnique<nscolor[]>(mNumRows);
852 for (int horX = 0; horX < mNumRows; horX++) {
853 horBordersVis[horX] = false;
854 horBorderColors[horX] = NO_COLOR;
855 }
856 }
857
858 // reflow the children
859 int32_t lastRow = 0;
860 int32_t lastCol = 0;
861 int32_t borderChildX = mNonBorderChildCount; // index of border children
862 nsHTMLFramesetBorderFrame* borderFrame = nullptr;
863 nsPoint offset(0, 0);
864 nsSize size, lastSize;
865 WritingMode wm = GetWritingMode();
866 LogicalSize logicalSize(wm);
867 nsIFrame* child = mFrames.FirstChild();
868
869 for (int32_t childX = 0; childX < mNonBorderChildCount; childX++) {
870 nsIntPoint cellIndex;
871 GetSizeOfChildAt(childX, wm, logicalSize, cellIndex);
872 size = logicalSize.GetPhysicalSize(wm);
873
874 if (lastRow != cellIndex.y) { // changed to next row
875 offset.x = 0;
876 offset.y += lastSize.height;
877 if (firstTime) { // create horizontal border
878
879 RefPtr<nsStyleContext> pseudoStyleContext;
880 pseudoStyleContext = styleSet->ResolveNonInheritingAnonymousBoxStyle(
881 nsCSSAnonBoxes::horizontalFramesetBorder);
882
883 borderFrame = new (shell) nsHTMLFramesetBorderFrame(
884 pseudoStyleContext, borderWidth, false, false);
885 borderFrame->Init(mContent, this, nullptr);
886 mChildCount++;
887 mFrames.AppendFrame(nullptr, borderFrame);
888 mHorBorders[cellIndex.y - 1] = borderFrame;
889 // set the neighbors for determining drag boundaries
890 borderFrame->mPrevNeighbor = lastRow;
891 borderFrame->mNextNeighbor = cellIndex.y;
892 } else {
893 borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
894 borderFrame->mWidth = borderWidth;
895 borderChildX++;
896 }
897 nsSize borderSize(aDesiredSize.Width(), borderWidth);
898 ReflowPlaceChild(borderFrame, aPresContext, aReflowInput, offset,
899 borderSize);
900 borderFrame = nullptr;
901 offset.y += borderWidth;
902 } else {
903 if (cellIndex.x > 0) { // moved to next col in same row
904 if (0 == cellIndex.y) { // in 1st row
905 if (firstTime) { // create vertical border
906
907 RefPtr<nsStyleContext> pseudoStyleContext;
908 pseudoStyleContext =
909 styleSet->ResolveNonInheritingAnonymousBoxStyle(
910 nsCSSAnonBoxes::verticalFramesetBorder);
911
912 borderFrame = new (shell) nsHTMLFramesetBorderFrame(
913 pseudoStyleContext, borderWidth, true, false);
914 borderFrame->Init(mContent, this, nullptr);
915 mChildCount++;
916 mFrames.AppendFrame(nullptr, borderFrame);
917 mVerBorders[cellIndex.x - 1] = borderFrame;
918 // set the neighbors for determining drag boundaries
919 borderFrame->mPrevNeighbor = lastCol;
920 borderFrame->mNextNeighbor = cellIndex.x;
921 } else {
922 borderFrame =
923 (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
924 borderFrame->mWidth = borderWidth;
925 borderChildX++;
926 }
927 nsSize borderSize(borderWidth, aDesiredSize.Height());
928 ReflowPlaceChild(borderFrame, aPresContext, aReflowInput, offset,
929 borderSize);
930 borderFrame = nullptr;
931 }
932 offset.x += borderWidth;
933 }
934 }
935
936 ReflowPlaceChild(child, aPresContext, aReflowInput, offset, size,
937 &cellIndex);
938
939 if (firstTime) {
940 int32_t childVis;
941 nsHTMLFramesetFrame* framesetFrame = do_QueryFrame(child);
942 nsSubDocumentFrame* subdocFrame;
943 if (framesetFrame) {
944 childVis = framesetFrame->mEdgeVisibility;
945 mChildBorderColors[childX] = framesetFrame->mEdgeColors;
946 } else if ((subdocFrame = do_QueryFrame(child))) {
947 if (eFrameborder_Yes == mChildFrameborder[childX]) {
948 childVis = ALL_VIS;
949 } else if (eFrameborder_No == mChildFrameborder[childX]) {
950 childVis = NONE_VIS;
951 } else { // notset
952 childVis = (eFrameborder_No == frameborder) ? NONE_VIS : ALL_VIS;
953 }
954 } else { // blank
955 #ifdef DEBUG
956 nsHTMLFramesetBlankFrame* blank = do_QueryFrame(child);
957 MOZ_ASSERT(blank, "unexpected child frame type");
958 #endif
959 childVis = NONE_VIS;
960 }
961 nsBorderColor childColors = mChildBorderColors[childX];
962 // set the visibility, color of our edge borders based on children
963 if (0 == cellIndex.x) {
964 if (!(mEdgeVisibility & LEFT_VIS)) {
965 mEdgeVisibility |= (LEFT_VIS & childVis);
966 }
967 if (NO_COLOR == mEdgeColors.mLeft) {
968 mEdgeColors.mLeft = childColors.mLeft;
969 }
970 }
971 if (0 == cellIndex.y) {
972 if (!(mEdgeVisibility & TOP_VIS)) {
973 mEdgeVisibility |= (TOP_VIS & childVis);
974 }
975 if (NO_COLOR == mEdgeColors.mTop) {
976 mEdgeColors.mTop = childColors.mTop;
977 }
978 }
979 if (mNumCols - 1 == cellIndex.x) {
980 if (!(mEdgeVisibility & RIGHT_VIS)) {
981 mEdgeVisibility |= (RIGHT_VIS & childVis);
982 }
983 if (NO_COLOR == mEdgeColors.mRight) {
984 mEdgeColors.mRight = childColors.mRight;
985 }
986 }
987 if (mNumRows - 1 == cellIndex.y) {
988 if (!(mEdgeVisibility & BOTTOM_VIS)) {
989 mEdgeVisibility |= (BOTTOM_VIS & childVis);
990 }
991 if (NO_COLOR == mEdgeColors.mBottom) {
992 mEdgeColors.mBottom = childColors.mBottom;
993 }
994 }
995 // set the visibility of borders that the child may affect
996 if (childVis & RIGHT_VIS) {
997 verBordersVis[cellIndex.x] = true;
998 }
999 if (childVis & BOTTOM_VIS) {
1000 horBordersVis[cellIndex.y] = true;
1001 }
1002 if ((cellIndex.x > 0) && (childVis & LEFT_VIS)) {
1003 verBordersVis[cellIndex.x - 1] = true;
1004 }
1005 if ((cellIndex.y > 0) && (childVis & TOP_VIS)) {
1006 horBordersVis[cellIndex.y - 1] = true;
1007 }
1008 // set the colors of borders that the child may affect
1009 if (NO_COLOR == verBorderColors[cellIndex.x]) {
1010 verBorderColors[cellIndex.x] = mChildBorderColors[childX].mRight;
1011 }
1012 if (NO_COLOR == horBorderColors[cellIndex.y]) {
1013 horBorderColors[cellIndex.y] = mChildBorderColors[childX].mBottom;
1014 }
1015 if ((cellIndex.x > 0) && (NO_COLOR == verBorderColors[cellIndex.x - 1])) {
1016 verBorderColors[cellIndex.x - 1] = mChildBorderColors[childX].mLeft;
1017 }
1018 if ((cellIndex.y > 0) && (NO_COLOR == horBorderColors[cellIndex.y - 1])) {
1019 horBorderColors[cellIndex.y - 1] = mChildBorderColors[childX].mTop;
1020 }
1021 }
1022 lastRow = cellIndex.y;
1023 lastCol = cellIndex.x;
1024 lastSize = size;
1025 offset.x += size.width;
1026 child = child->GetNextSibling();
1027 }
1028
1029 if (firstTime) {
1030 nscolor childColor;
1031 // set the visibility, color, mouse sensitivity of borders
1032 for (int verX = 0; verX < mNumCols - 1; verX++) {
1033 if (mVerBorders[verX]) {
1034 mVerBorders[verX]->SetVisibility(verBordersVis[verX]);
1035 SetBorderResize(mVerBorders[verX]);
1036 childColor = (NO_COLOR == verBorderColors[verX])
1037 ? borderColor
1038 : verBorderColors[verX];
1039 mVerBorders[verX]->SetColor(childColor);
1040 }
1041 }
1042 for (int horX = 0; horX < mNumRows - 1; horX++) {
1043 if (mHorBorders[horX]) {
1044 mHorBorders[horX]->SetVisibility(horBordersVis[horX]);
1045 SetBorderResize(mHorBorders[horX]);
1046 childColor = (NO_COLOR == horBorderColors[horX])
1047 ? borderColor
1048 : horBorderColors[horX];
1049 mHorBorders[horX]->SetColor(childColor);
1050 }
1051 }
1052
1053 mChildFrameborder.reset();
1054 mChildBorderColors.reset();
1055 }
1056
1057 mDrag.UnSet();
1058
1059 aDesiredSize.SetOverflowAreasToDesiredBounds();
1060 FinishAndStoreOverflow(&aDesiredSize);
1061
1062 NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
1063 }
1064
1065 #ifdef DEBUG_FRAME_DUMP
GetFrameName(nsAString & aResult) const1066 nsresult nsHTMLFramesetFrame::GetFrameName(nsAString& aResult) const {
1067 return MakeFrameName(NS_LITERAL_STRING("Frameset"), aResult);
1068 }
1069 #endif
1070
CanResize(bool aVertical,bool aLeft)1071 bool nsHTMLFramesetFrame::CanResize(bool aVertical, bool aLeft) {
1072 int32_t childX;
1073 int32_t startX;
1074 if (aVertical) {
1075 startX = (aLeft) ? 0 : mNumCols - 1;
1076 for (childX = startX; childX < mNonBorderChildCount; childX += mNumCols) {
1077 if (!CanChildResize(aVertical, aLeft, childX)) {
1078 return false;
1079 }
1080 }
1081 } else {
1082 startX = (aLeft) ? 0 : (mNumRows - 1) * mNumCols;
1083 int32_t endX = startX + mNumCols;
1084 for (childX = startX; childX < endX; childX++) {
1085 if (!CanChildResize(aVertical, aLeft, childX)) {
1086 return false;
1087 }
1088 }
1089 }
1090 return true;
1091 }
1092
GetNoResize(nsIFrame * aChildFrame)1093 bool nsHTMLFramesetFrame::GetNoResize(nsIFrame* aChildFrame) {
1094 nsIContent* content = aChildFrame->GetContent();
1095
1096 return content && content->IsElement() &&
1097 content->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::noresize);
1098 }
1099
CanChildResize(bool aVertical,bool aLeft,int32_t aChildX)1100 bool nsHTMLFramesetFrame::CanChildResize(bool aVertical, bool aLeft,
1101 int32_t aChildX) {
1102 nsIFrame* child = mFrames.FrameAt(aChildX);
1103 nsHTMLFramesetFrame* frameset = do_QueryFrame(child);
1104 return frameset ? frameset->CanResize(aVertical, aLeft) : !GetNoResize(child);
1105 }
1106
1107 // This calculates and sets the resizability of all border frames
1108
RecalculateBorderResize()1109 void nsHTMLFramesetFrame::RecalculateBorderResize() {
1110 if (!mContent) {
1111 return;
1112 }
1113
1114 static_assert(
1115 NS_MAX_FRAMESET_SPEC_COUNT < INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT,
1116 "Check for overflow");
1117 static_assert(NS_MAX_FRAMESET_SPEC_COUNT <
1118 UINT_MAX / sizeof(int32_t) / NS_MAX_FRAMESET_SPEC_COUNT,
1119 "Check for overflow");
1120 // set the visibility and mouse sensitivity of borders
1121 int32_t verX;
1122 for (verX = 0; verX < mNumCols - 1; verX++) {
1123 if (mVerBorders[verX]) {
1124 mVerBorders[verX]->mCanResize = true;
1125 SetBorderResize(mVerBorders[verX]);
1126 }
1127 }
1128 int32_t horX;
1129 for (horX = 0; horX < mNumRows - 1; horX++) {
1130 if (mHorBorders[horX]) {
1131 mHorBorders[horX]->mCanResize = true;
1132 SetBorderResize(mHorBorders[horX]);
1133 }
1134 }
1135 }
1136
SetBorderResize(nsHTMLFramesetBorderFrame * aBorderFrame)1137 void nsHTMLFramesetFrame::SetBorderResize(
1138 nsHTMLFramesetBorderFrame* aBorderFrame) {
1139 if (aBorderFrame->mVertical) {
1140 for (int rowX = 0; rowX < mNumRows; rowX++) {
1141 int32_t childX = aBorderFrame->mPrevNeighbor + (rowX * mNumCols);
1142 if (!CanChildResize(true, false, childX) ||
1143 !CanChildResize(true, true, childX + 1)) {
1144 aBorderFrame->mCanResize = false;
1145 }
1146 }
1147 } else {
1148 int32_t childX = aBorderFrame->mPrevNeighbor * mNumCols;
1149 int32_t endX = childX + mNumCols;
1150 for (; childX < endX; childX++) {
1151 if (!CanChildResize(false, false, childX)) {
1152 aBorderFrame->mCanResize = false;
1153 }
1154 }
1155 endX = endX + mNumCols;
1156 for (; childX < endX; childX++) {
1157 if (!CanChildResize(false, true, childX)) {
1158 aBorderFrame->mCanResize = false;
1159 }
1160 }
1161 }
1162 }
1163
StartMouseDrag(nsPresContext * aPresContext,nsHTMLFramesetBorderFrame * aBorder,WidgetGUIEvent * aEvent)1164 void nsHTMLFramesetFrame::StartMouseDrag(nsPresContext* aPresContext,
1165 nsHTMLFramesetBorderFrame* aBorder,
1166 WidgetGUIEvent* aEvent) {
1167 #if 0
1168 int32_t index;
1169 IndexOf(aBorder, index);
1170 NS_ASSERTION((nullptr != aBorder) && (index >= 0), "invalid dragger");
1171 #endif
1172
1173 nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
1174
1175 mDragger = aBorder;
1176
1177 mFirstDragPoint = aEvent->mRefPoint;
1178
1179 // Store the original frame sizes
1180 if (mDragger->mVertical) {
1181 mPrevNeighborOrigSize = mColSizes[mDragger->mPrevNeighbor];
1182 mNextNeighborOrigSize = mColSizes[mDragger->mNextNeighbor];
1183 } else {
1184 mPrevNeighborOrigSize = mRowSizes[mDragger->mPrevNeighbor];
1185 mNextNeighborOrigSize = mRowSizes[mDragger->mNextNeighbor];
1186 }
1187
1188 gDragInProgress = true;
1189 }
1190
MouseDrag(nsPresContext * aPresContext,WidgetGUIEvent * aEvent)1191 void nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
1192 WidgetGUIEvent* aEvent) {
1193 // if the capture ended, reset the drag state
1194 if (nsIPresShell::GetCapturingContent() != GetContent()) {
1195 mDragger = nullptr;
1196 gDragInProgress = false;
1197 return;
1198 }
1199
1200 int32_t change; // measured positive from left-to-right or top-to-bottom
1201 AutoWeakFrame weakFrame(this);
1202 if (mDragger->mVertical) {
1203 change = aPresContext->DevPixelsToAppUnits(aEvent->mRefPoint.x -
1204 mFirstDragPoint.x);
1205 if (change > mNextNeighborOrigSize - mMinDrag) {
1206 change = mNextNeighborOrigSize - mMinDrag;
1207 } else if (change <= mMinDrag - mPrevNeighborOrigSize) {
1208 change = mMinDrag - mPrevNeighborOrigSize;
1209 }
1210 mColSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change;
1211 mColSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change;
1212
1213 if (change != 0) {
1214 // Recompute the specs from the new sizes.
1215 nscoord width =
1216 mRect.width - (mNumCols - 1) * GetBorderWidth(aPresContext, true);
1217 HTMLFrameSetElement* ourContent =
1218 HTMLFrameSetElement::FromContent(mContent);
1219 NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
1220 const nsFramesetSpec* colSpecs = nullptr;
1221 ourContent->GetColSpec(&mNumCols, &colSpecs);
1222 nsAutoString newColAttr;
1223 GenerateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes.get(),
1224 newColAttr);
1225 // Setting the attr will trigger a reflow
1226 mContent->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::cols,
1227 newColAttr, true);
1228 }
1229 } else {
1230 change = aPresContext->DevPixelsToAppUnits(aEvent->mRefPoint.y -
1231 mFirstDragPoint.y);
1232 if (change > mNextNeighborOrigSize - mMinDrag) {
1233 change = mNextNeighborOrigSize - mMinDrag;
1234 } else if (change <= mMinDrag - mPrevNeighborOrigSize) {
1235 change = mMinDrag - mPrevNeighborOrigSize;
1236 }
1237 mRowSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change;
1238 mRowSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change;
1239
1240 if (change != 0) {
1241 // Recompute the specs from the new sizes.
1242 nscoord height =
1243 mRect.height - (mNumRows - 1) * GetBorderWidth(aPresContext, true);
1244 HTMLFrameSetElement* ourContent =
1245 HTMLFrameSetElement::FromContent(mContent);
1246 NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
1247 const nsFramesetSpec* rowSpecs = nullptr;
1248 ourContent->GetRowSpec(&mNumRows, &rowSpecs);
1249 nsAutoString newRowAttr;
1250 GenerateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes.get(),
1251 newRowAttr);
1252 // Setting the attr will trigger a reflow
1253 mContent->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::rows,
1254 newRowAttr, true);
1255 }
1256 }
1257
1258 ENSURE_TRUE(weakFrame.IsAlive());
1259 if (change != 0) {
1260 mDrag.Reset(mDragger->mVertical, mDragger->mPrevNeighbor, change, this);
1261 }
1262 }
1263
EndMouseDrag(nsPresContext * aPresContext)1264 void nsHTMLFramesetFrame::EndMouseDrag(nsPresContext* aPresContext) {
1265 nsIPresShell::SetCapturingContent(nullptr, 0);
1266 mDragger = nullptr;
1267 gDragInProgress = false;
1268 }
1269
NS_NewHTMLFramesetFrame(nsIPresShell * aPresShell,nsStyleContext * aContext)1270 nsIFrame* NS_NewHTMLFramesetFrame(nsIPresShell* aPresShell,
1271 nsStyleContext* aContext) {
1272 #ifdef DEBUG
1273 const nsStyleDisplay* disp = aContext->StyleDisplay();
1274 NS_ASSERTION(!disp->IsAbsolutelyPositionedStyle() && !disp->IsFloatingStyle(),
1275 "Framesets should not be positioned and should not float");
1276 #endif
1277
1278 return new (aPresShell) nsHTMLFramesetFrame(aContext);
1279 }
1280
NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetFrame)1281 NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetFrame)
1282
1283 /*******************************************************************************
1284 * nsHTMLFramesetBorderFrame
1285 ******************************************************************************/
1286 nsHTMLFramesetBorderFrame::nsHTMLFramesetBorderFrame(nsStyleContext* aContext,
1287 int32_t aWidth,
1288 bool aVertical,
1289 bool aVisibility)
1290 : nsLeafFrame(aContext, kClassID),
1291 mWidth(aWidth),
1292 mVertical(aVertical),
1293 mVisibility(aVisibility) {
1294 mCanResize = true;
1295 mColor = NO_COLOR;
1296 mPrevNeighbor = 0;
1297 mNextNeighbor = 0;
1298 }
1299
~nsHTMLFramesetBorderFrame()1300 nsHTMLFramesetBorderFrame::~nsHTMLFramesetBorderFrame() {
1301 // printf("nsHTMLFramesetBorderFrame destructor %p \n", this);
1302 }
1303
NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetBorderFrame)1304 NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetBorderFrame)
1305
1306 nscoord nsHTMLFramesetBorderFrame::GetIntrinsicISize() {
1307 // No intrinsic width
1308 return 0;
1309 }
1310
GetIntrinsicBSize()1311 nscoord nsHTMLFramesetBorderFrame::GetIntrinsicBSize() {
1312 // No intrinsic height
1313 return 0;
1314 }
1315
SetVisibility(bool aVisibility)1316 void nsHTMLFramesetBorderFrame::SetVisibility(bool aVisibility) {
1317 mVisibility = aVisibility;
1318 }
1319
SetColor(nscolor aColor)1320 void nsHTMLFramesetBorderFrame::SetColor(nscolor aColor) { mColor = aColor; }
1321
Reflow(nsPresContext * aPresContext,ReflowOutput & aDesiredSize,const ReflowInput & aReflowInput,nsReflowStatus & aStatus)1322 void nsHTMLFramesetBorderFrame::Reflow(nsPresContext* aPresContext,
1323 ReflowOutput& aDesiredSize,
1324 const ReflowInput& aReflowInput,
1325 nsReflowStatus& aStatus) {
1326 DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame");
1327 DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
1328 MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
1329
1330 // Override Reflow(), since we don't want to deal with what our
1331 // computed values are.
1332 SizeToAvailSize(aReflowInput, aDesiredSize);
1333
1334 aDesiredSize.SetOverflowAreasToDesiredBounds();
1335 }
1336
1337 class nsDisplayFramesetBorder : public nsDisplayItem {
1338 public:
nsDisplayFramesetBorder(nsDisplayListBuilder * aBuilder,nsHTMLFramesetBorderFrame * aFrame)1339 nsDisplayFramesetBorder(nsDisplayListBuilder* aBuilder,
1340 nsHTMLFramesetBorderFrame* aFrame)
1341 : nsDisplayItem(aBuilder, aFrame) {
1342 MOZ_COUNT_CTOR(nsDisplayFramesetBorder);
1343 }
1344 #ifdef NS_BUILD_REFCNT_LOGGING
~nsDisplayFramesetBorder()1345 virtual ~nsDisplayFramesetBorder() {
1346 MOZ_COUNT_DTOR(nsDisplayFramesetBorder);
1347 }
1348 #endif
1349
1350 // REVIEW: see old GetFrameForPoint
1351 // Receives events in its bounds
HitTest(nsDisplayListBuilder * aBuilder,const nsRect & aRect,HitTestState * aState,nsTArray<nsIFrame * > * aOutFrames)1352 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1353 HitTestState* aState,
1354 nsTArray<nsIFrame*>* aOutFrames) override {
1355 aOutFrames->AppendElement(mFrame);
1356 }
1357 virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
1358 NS_DISPLAY_DECL_NAME("FramesetBorder", TYPE_FRAMESET_BORDER)
1359 };
1360
Paint(nsDisplayListBuilder * aBuilder,gfxContext * aCtx)1361 void nsDisplayFramesetBorder::Paint(nsDisplayListBuilder* aBuilder,
1362 gfxContext* aCtx) {
1363 static_cast<nsHTMLFramesetBorderFrame*>(mFrame)->PaintBorder(
1364 aCtx->GetDrawTarget(), ToReferenceFrame());
1365 }
1366
BuildDisplayList(nsDisplayListBuilder * aBuilder,const nsDisplayListSet & aLists)1367 void nsHTMLFramesetBorderFrame::BuildDisplayList(
1368 nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) {
1369 aLists.Content()->AppendToTop(
1370 MakeDisplayItem<nsDisplayFramesetBorder>(aBuilder, this));
1371 }
1372
PaintBorder(DrawTarget * aDrawTarget,nsPoint aPt)1373 void nsHTMLFramesetBorderFrame::PaintBorder(DrawTarget* aDrawTarget,
1374 nsPoint aPt) {
1375 nscoord widthInPixels = nsPresContext::AppUnitsToIntCSSPixels(mWidth);
1376 nscoord pixelWidth = nsPresContext::CSSPixelsToAppUnits(1);
1377
1378 if (widthInPixels <= 0) return;
1379
1380 ColorPattern bgColor(ToDeviceColor(LookAndFeel::GetColor(
1381 LookAndFeel::eColorID_WidgetBackground, NS_RGB(200, 200, 200))));
1382
1383 ColorPattern fgColor(ToDeviceColor(LookAndFeel::GetColor(
1384 LookAndFeel::eColorID_WidgetForeground, NS_RGB(0, 0, 0))));
1385
1386 ColorPattern hltColor(ToDeviceColor(LookAndFeel::GetColor(
1387 LookAndFeel::eColorID_Widget3DHighlight, NS_RGB(255, 255, 255))));
1388
1389 ColorPattern sdwColor(ToDeviceColor(LookAndFeel::GetColor(
1390 LookAndFeel::eColorID_Widget3DShadow, NS_RGB(128, 128, 128))));
1391
1392 ColorPattern color(ToDeviceColor(NS_RGB(255, 255, 255))); // default to white
1393 if (mVisibility) {
1394 color =
1395 (NO_COLOR == mColor) ? bgColor : ColorPattern(ToDeviceColor(mColor));
1396 }
1397
1398 int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
1399
1400 Point toRefFrame = NSPointToPoint(aPt, appUnitsPerDevPixel);
1401
1402 AutoRestoreTransform autoRestoreTransform(aDrawTarget);
1403 aDrawTarget->SetTransform(
1404 aDrawTarget->GetTransform().PreTranslate(toRefFrame));
1405
1406 nsPoint start(0, 0);
1407 nsPoint end = mVertical ? nsPoint(0, mRect.height) : nsPoint(mRect.width, 0);
1408
1409 // draw grey or white first
1410 for (int i = 0; i < widthInPixels; i++) {
1411 StrokeLineWithSnapping(start, end, appUnitsPerDevPixel, *aDrawTarget,
1412 color);
1413 if (mVertical) {
1414 start.x += pixelWidth;
1415 end.x = start.x;
1416 } else {
1417 start.y += pixelWidth;
1418 end.y = start.y;
1419 }
1420 }
1421
1422 if (!mVisibility) return;
1423
1424 if (widthInPixels >= 5) {
1425 start.x = (mVertical) ? pixelWidth : 0;
1426 start.y = (mVertical) ? 0 : pixelWidth;
1427 end.x = (mVertical) ? start.x : mRect.width;
1428 end.y = (mVertical) ? mRect.height : start.y;
1429 StrokeLineWithSnapping(start, end, appUnitsPerDevPixel, *aDrawTarget,
1430 hltColor);
1431 }
1432
1433 if (widthInPixels >= 2) {
1434 start.x = (mVertical) ? mRect.width - (2 * pixelWidth) : 0;
1435 start.y = (mVertical) ? 0 : mRect.height - (2 * pixelWidth);
1436 end.x = (mVertical) ? start.x : mRect.width;
1437 end.y = (mVertical) ? mRect.height : start.y;
1438 StrokeLineWithSnapping(start, end, appUnitsPerDevPixel, *aDrawTarget,
1439 sdwColor);
1440 }
1441
1442 if (widthInPixels >= 1) {
1443 start.x = (mVertical) ? mRect.width - pixelWidth : 0;
1444 start.y = (mVertical) ? 0 : mRect.height - pixelWidth;
1445 end.x = (mVertical) ? start.x : mRect.width;
1446 end.y = (mVertical) ? mRect.height : start.y;
1447 StrokeLineWithSnapping(start, end, appUnitsPerDevPixel, *aDrawTarget,
1448 fgColor);
1449 }
1450 }
1451
HandleEvent(nsPresContext * aPresContext,WidgetGUIEvent * aEvent,nsEventStatus * aEventStatus)1452 nsresult nsHTMLFramesetBorderFrame::HandleEvent(nsPresContext* aPresContext,
1453 WidgetGUIEvent* aEvent,
1454 nsEventStatus* aEventStatus) {
1455 NS_ENSURE_ARG_POINTER(aEventStatus);
1456 *aEventStatus = nsEventStatus_eIgnore;
1457
1458 // XXX Mouse setting logic removed. The remaining logic should also move.
1459 if (!mCanResize) {
1460 return NS_OK;
1461 }
1462
1463 if (aEvent->mMessage == eMouseDown &&
1464 aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
1465 nsHTMLFramesetFrame* parentFrame = do_QueryFrame(GetParent());
1466 if (parentFrame) {
1467 parentFrame->StartMouseDrag(aPresContext, this, aEvent);
1468 *aEventStatus = nsEventStatus_eConsumeNoDefault;
1469 }
1470 }
1471 return NS_OK;
1472 }
1473
GetCursor(const nsPoint & aPoint,nsIFrame::Cursor & aCursor)1474 nsresult nsHTMLFramesetBorderFrame::GetCursor(const nsPoint& aPoint,
1475 nsIFrame::Cursor& aCursor) {
1476 aCursor.mLoading = false;
1477 if (!mCanResize) {
1478 aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
1479 } else {
1480 aCursor.mCursor =
1481 (mVertical) ? NS_STYLE_CURSOR_EW_RESIZE : NS_STYLE_CURSOR_NS_RESIZE;
1482 }
1483 return NS_OK;
1484 }
1485
1486 #ifdef DEBUG_FRAME_DUMP
GetFrameName(nsAString & aResult) const1487 nsresult nsHTMLFramesetBorderFrame::GetFrameName(nsAString& aResult) const {
1488 return MakeFrameName(NS_LITERAL_STRING("FramesetBorder"), aResult);
1489 }
1490 #endif
1491
1492 /*******************************************************************************
1493 * nsHTMLFramesetBlankFrame
1494 ******************************************************************************/
1495
1496 NS_QUERYFRAME_HEAD(nsHTMLFramesetBlankFrame)
NS_QUERYFRAME_ENTRY(nsHTMLFramesetBlankFrame)1497 NS_QUERYFRAME_ENTRY(nsHTMLFramesetBlankFrame)
1498 NS_QUERYFRAME_TAIL_INHERITING(nsLeafFrame)
1499
1500 NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetBlankFrame)
1501
1502 nsHTMLFramesetBlankFrame::~nsHTMLFramesetBlankFrame() {
1503 // printf("nsHTMLFramesetBlankFrame destructor %p \n", this);
1504 }
1505
GetIntrinsicISize()1506 nscoord nsHTMLFramesetBlankFrame::GetIntrinsicISize() {
1507 // No intrinsic width
1508 return 0;
1509 }
1510
GetIntrinsicBSize()1511 nscoord nsHTMLFramesetBlankFrame::GetIntrinsicBSize() {
1512 // No intrinsic height
1513 return 0;
1514 }
1515
Reflow(nsPresContext * aPresContext,ReflowOutput & aDesiredSize,const ReflowInput & aReflowInput,nsReflowStatus & aStatus)1516 void nsHTMLFramesetBlankFrame::Reflow(nsPresContext* aPresContext,
1517 ReflowOutput& aDesiredSize,
1518 const ReflowInput& aReflowInput,
1519 nsReflowStatus& aStatus) {
1520 DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame");
1521 MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
1522
1523 // Override Reflow(), since we don't want to deal with what our
1524 // computed values are.
1525 SizeToAvailSize(aReflowInput, aDesiredSize);
1526
1527 aDesiredSize.SetOverflowAreasToDesiredBounds();
1528 }
1529
1530 class nsDisplayFramesetBlank : public nsDisplayItem {
1531 public:
nsDisplayFramesetBlank(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)1532 nsDisplayFramesetBlank(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
1533 : nsDisplayItem(aBuilder, aFrame) {
1534 MOZ_COUNT_CTOR(nsDisplayFramesetBlank);
1535 }
1536 #ifdef NS_BUILD_REFCNT_LOGGING
~nsDisplayFramesetBlank()1537 virtual ~nsDisplayFramesetBlank() { MOZ_COUNT_DTOR(nsDisplayFramesetBlank); }
1538 #endif
1539
1540 virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
1541 NS_DISPLAY_DECL_NAME("FramesetBlank", TYPE_FRAMESET_BLANK)
1542 };
1543
Paint(nsDisplayListBuilder * aBuilder,gfxContext * aCtx)1544 void nsDisplayFramesetBlank::Paint(nsDisplayListBuilder* aBuilder,
1545 gfxContext* aCtx) {
1546 DrawTarget* drawTarget = aCtx->GetDrawTarget();
1547 int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
1548 Rect rect =
1549 NSRectToSnappedRect(mVisibleRect, appUnitsPerDevPixel, *drawTarget);
1550 ColorPattern white(ToDeviceColor(Color(1.f, 1.f, 1.f, 1.f)));
1551 drawTarget->FillRect(rect, white);
1552 }
1553
BuildDisplayList(nsDisplayListBuilder * aBuilder,const nsDisplayListSet & aLists)1554 void nsHTMLFramesetBlankFrame::BuildDisplayList(
1555 nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) {
1556 aLists.Content()->AppendToTop(
1557 MakeDisplayItem<nsDisplayFramesetBlank>(aBuilder, this));
1558 }
1559