Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/layout/generic/nsFrameSetFrame.cpp
Warning:line 941, column 19
Although the value stored to 'subdocFrame' is used in the enclosing expression, the value is never actually read from 'subdocFrame'

Annotated Source Code

Press '?' to see keyboard shortcuts

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