nsLayoutUtils.h 138 KB
Newer Older
1
2
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
4
5
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
8
9

#ifndef nsLayoutUtils_h__
#define nsLayoutUtils_h__

10
#include "LayoutConstants.h"
11
#include "mozilla/MemoryReporting.h"
12
#include "mozilla/ArrayUtils.h"
13
#include "mozilla/LookAndFeel.h"
14
#include "mozilla/Maybe.h"
15
#include "mozilla/RelativeTo.h"
16
#include "mozilla/StaticPrefs_nglayout.h"
17
#include "mozilla/TypedEnumBits.h"
18
#include "mozilla/UniquePtr.h"
19
#include "nsBoundingMetrics.h"
20
#include "mozilla/layout/FrameChildList.h"
21
#include "mozilla/layers/ScrollableLayerGuid.h"
22
#include "nsThreadUtils.h"
23
#include "nsCSSPropertyIDSet.h"
24
25
26
#include "nsGkAtoms.h"
#include "mozilla/gfx/2D.h"
#include "Units.h"
27
#include "mozilla/ToString.h"
28
#include "mozilla/ReflowOutput.h"
29
#include "ImageContainer.h"  // for layers::Image
30
#include "gfx2DGlue.h"
31
#include "SVGImageContext.h"
32
33
#include <limits>
#include <algorithm>
34
#include "gfxPoint.h"
35
#include "nsClassHashtable.h"
36

37
class gfxContext;
38
39
40
class gfxFontEntry;
class imgIContainer;
class nsFrameList;
41
class nsPresContext;
42
class nsIContent;
43
44
class nsIPrincipal;
class nsIWidget;
45
class nsAtom;
46
class nsIScrollableFrame;
47
class nsRegion;
48
class nsDisplayListBuilder;
49
enum class nsDisplayListBuilderMode : uint8_t;
50
enum nsChangeHint : uint32_t;
51
class nsDisplayItem;
52
class nsFontMetrics;
53
class nsFontFaceList;
54
class nsIImageLoadingContent;
55
class nsBlockFrame;
56
class nsContainerFrame;
57
class nsView;
58
class nsIFrame;
59
class nsPIDOMWindowOuter;
60
61
62
class imgIRequest;
struct nsStyleFont;
struct nsOverflowAreas;
63

64
namespace mozilla {
65
struct AspectRatio;
66
class ComputedStyle;
67
class PresShell;
68
enum class PseudoStyleType : uint8_t;
69
class EventListenerManager;
70
enum class LayoutFrameType : uint8_t;
71
struct IntrinsicSize;
72
struct ContainerLayerParameters;
73
class WritingMode;
74
class DisplayItemClip;
75
class EffectSet;
76
struct ActiveScrolledRoot;
77
enum class StyleImageOrientation : uint8_t;
78
namespace dom {
79
class CanvasRenderingContext2D;
80
class DOMRectList;
81
class Document;
82
class Element;
83
class Event;
84
class HTMLImageElement;
85
class HTMLCanvasElement;
86
class HTMLVideoElement;
87
class InspectorFontFace;
88
class OffscreenCanvas;
89
class Selection;
90
}  // namespace dom
91
92
namespace gfx {
struct RectCornerRadii;
93
enum class ShapedTextFlags : uint16_t;
94
}  // namespace gfx
95
namespace layers {
96
97
struct FrameMetrics;
struct ScrollMetadata;
98
class Image;
Andrew Osmond's avatar
Andrew Osmond committed
99
class StackingContextHelper;
100
class Layer;
101
102
}  // namespace layers
}  // namespace mozilla
103
104
105
106

namespace mozilla {

struct DisplayPortPropertyData {
107
108
109
  DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority,
                          bool aPainted)
      : mRect(aRect), mPriority(aPriority), mPainted(aPainted) {}
110
111
  nsRect mRect;
  uint32_t mPriority;
112
  bool mPainted;
113
};
114

115
struct DisplayPortMarginsPropertyData {
116
  DisplayPortMarginsPropertyData(const ScreenMargin& aMargins,
117
118
                                 uint32_t aPriority, bool aPainted)
      : mMargins(aMargins), mPriority(aPriority), mPainted(aPainted) {}
119
  ScreenMargin mMargins;
120
  uint32_t mPriority;
121
  bool mPainted;
122
123
};

124
}  // namespace mozilla
125

126
// For GetDisplayPort
127
enum class DisplayportRelativeTo { ScrollPort, ScrollFrame };
128

129
130
// Flags to customize the behavior of nsLayoutUtils::DrawString.
enum class DrawStringFlags {
131
132
  Default = 0x0,
  ForceHorizontal = 0x1  // Forces the text to be drawn horizontally.
133
134
135
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DrawStringFlags)

136
137
138
139
140
/**
 * nsLayoutUtils is a namespace class used for various helper
 * functions that are useful in multiple places in layout.  The goal
 * is not to define multiple copies of the same static helper.
 */
141
class nsLayoutUtils {
142
  typedef mozilla::AspectRatio AspectRatio;
143
  typedef mozilla::ComputedStyle ComputedStyle;
144
  typedef mozilla::LengthPercentage LengthPercentage;
145
  typedef mozilla::LengthPercentageOrAuto LengthPercentageOrAuto;
146
  typedef mozilla::dom::DOMRectList DOMRectList;
147
  typedef mozilla::layers::Layer Layer;
Andrew Osmond's avatar
Andrew Osmond committed
148
  typedef mozilla::layers::StackingContextHelper StackingContextHelper;
149
  typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
150
  typedef mozilla::IntrinsicSize IntrinsicSize;
151
152
  typedef mozilla::RelativeTo RelativeTo;
  typedef mozilla::ViewportType ViewportType;
153
  typedef mozilla::gfx::SourceSurface SourceSurface;
154
  typedef mozilla::gfx::sRGBColor sRGBColor;
155
  typedef mozilla::gfx::DrawTarget DrawTarget;
156
  typedef mozilla::gfx::ExtendMode ExtendMode;
157
  typedef mozilla::gfx::SamplingFilter SamplingFilter;
158
  typedef mozilla::gfx::Float Float;
159
  typedef mozilla::gfx::Point Point;
160
  typedef mozilla::gfx::Rect Rect;
161
  typedef mozilla::gfx::RectDouble RectDouble;
162
  typedef mozilla::gfx::Size Size;
163
  typedef mozilla::gfx::Matrix4x4 Matrix4x4;
164
  typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged;
165
  typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
166
  typedef mozilla::gfx::StrokeOptions StrokeOptions;
167
  typedef mozilla::image::ImgDrawResult ImgDrawResult;
168

169
 public:
170
  typedef mozilla::layers::FrameMetrics FrameMetrics;
171
  typedef mozilla::layers::ScrollMetadata ScrollMetadata;
172
  typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID;
173
  typedef mozilla::CSSPoint CSSPoint;
174
  typedef mozilla::CSSSize CSSSize;
175
  typedef mozilla::CSSIntSize CSSIntSize;
176
  typedef mozilla::CSSRect CSSRect;
177
  typedef mozilla::ScreenMargin ScreenMargin;
178
  typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize;
Andrew Osmond's avatar
Andrew Osmond committed
179
  typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
180
  typedef mozilla::PresShell PresShell;
181
  typedef mozilla::StyleGeometryBox StyleGeometryBox;
182
  typedef mozilla::SVGImageContext SVGImageContext;
183
  typedef mozilla::LogicalSize LogicalSize;
184

185
186
187
188
  /**
   * Finds previously assigned ViewID for the given content element, if any.
   * Returns whether a ViewID was previously assigned.
   */
189
  static bool FindIDFor(const nsIContent* aContent, ViewID* aOutViewId);
190

191
192
  /**
   * Finds previously assigned or generates a unique ViewID for the given
193
   * content element.
194
   */
195
  static ViewID FindOrCreateIDFor(nsIContent* aContent);
196
197
198
199
200
201

  /**
   * Find content for given ID.
   */
  static nsIContent* FindContentFor(ViewID aId);

202
203
204
205
206
  /**
   * Find the scrollable frame for a given content element.
   */
  static nsIScrollableFrame* FindScrollableFrameFor(nsIContent* aContent);

207
208
209
210
211
  /**
   * Find the scrollable frame for a given ID.
   */
  static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId);

212
213
214
215
216
  /**
   * Find the ID for a given scrollable frame.
   */
  static ViewID FindIDForScrollableFrame(nsIScrollableFrame* aScrollable);

217
  /**
218
219
   * Get display port for the given element, relative to the specified entity,
   * defaulting to the scrollport.
220
   */
221
222
223
224
  static bool GetDisplayPort(
      nsIContent* aContent, nsRect* aResult,
      DisplayportRelativeTo aRelativeTo = DisplayportRelativeTo::ScrollPort,
      bool* aOutPainted = nullptr);
225

226
227
228
229
  /**
   * Check whether the given element has a displayport.
   */
  static bool HasDisplayPort(nsIContent* aContent);
230

231
232
233
234
235
236
237
238
239
240
241
242
  /**
   * Check whether the given element has a displayport that has already
   * been sent to the compositor via a layers or WR transaction.
   */
  static bool HasPaintedDisplayPort(nsIContent* aContent);

  /**
   * Mark the displayport of a given element as having been sent to
   * the compositor via a layers or WR transaction.
   */
  static void MarkDisplayPortAsPainted(nsIContent* aContent);

243
244
245
246
247
248
  /**
   * Check whether the given frame has a displayport. It returns false
   * for scrolled frames and true for the corresponding scroll frame.
   * Optionally pass the child, and it only returns true if the child is the
   * scrolled frame for the displayport.
   */
249
250
  static bool FrameHasDisplayPort(nsIFrame* aFrame,
                                  const nsIFrame* aScrolledFrame = nullptr);
251

252
253
254
255
256
  /**
   * Check if the given element has a margins based displayport but is missing a
   * displayport base rect that it needs to properly compute a displayport rect.
   */
  static bool IsMissingDisplayPortBaseRect(nsIContent* aContent);
257
258
259
260
261
262
263
264
265
266

  /**
   * Go through the IPC Channel and update displayport margins for content
   * elements based on UpdateFrame messages. The messages are left in the
   * queue and will be fully processed when dequeued. The aim is to paint
   * the most up-to-date displayport without waiting for these message to
   * go through the message queue.
   */
  static void UpdateDisplayPortMarginsFromPendingMessages();

267
268
269
270
  /**
   * @return the display port for the given element which should be used for
   * visibility testing purposes.
   *
271
272
   * If low-precision buffers are enabled, this is the critical display port;
   * otherwise, it's the same display port returned by GetDisplayPort().
273
   */
274
  static bool GetDisplayPortForVisibilityTesting(
275
      nsIContent* aContent, nsRect* aResult,
276
      DisplayportRelativeTo aRelativeTo = DisplayportRelativeTo::ScrollPort);
277

278
  enum class RepaintMode : uint8_t { Repaint, DoNotRepaint };
279

280
281
282
  /**
   * Invalidate for displayport change.
   */
283
284
285
286
  static void InvalidateForDisplayPortChange(
      nsIContent* aContent, bool aHadDisplayPort, const nsRect& aOldDisplayPort,
      const nsRect& aNewDisplayPort,
      RepaintMode aRepaintMode = RepaintMode::Repaint);
287

288
289
290
291
292
293
294
295
296
297
298
299
300
  /**
   * Set the display port margins for a content element to be used with a
   * display port base (see SetDisplayPortBase()).
   * See also nsIDOMWindowUtils.setDisplayPortMargins.
   * @param aContent the content element for which to set the margins
   * @param aPresShell the pres shell for the document containing the element
   * @param aMargins the margins to set
   * @param aAlignmentX, alignmentY the amount of pixels to which to align the
   *                                displayport built by combining the base
   *                                rect with the margins, in either direction
   * @param aPriority a priority value to determine which margins take effect
   *                  when multiple callers specify margins
   * @param aRepaintMode whether to schedule a paint after setting the margins
301
   * @return true if the new margins were applied.
302
   */
303
  static bool SetDisplayPortMargins(
304
305
      nsIContent* aContent, PresShell* aPresShell, const ScreenMargin& aMargins,
      uint32_t aPriority = 0, RepaintMode aRepaintMode = RepaintMode::Repaint);
306
307
308
309

  /**
   * Set the display port base rect for given element to be used with display
   * port margins.
310
311
   * SetDisplayPortBaseIfNotSet is like SetDisplayPortBase except it only sets
   * the display port base to aBase if no display port base is currently set.
312
313
   */
  static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase);
314
315
  static void SetDisplayPortBaseIfNotSet(nsIContent* aContent,
                                         const nsRect& aBase);
316

317
318
319
  /**
   * Get the critical display port for the given element.
   */
320
321
  static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult,
                                     bool* aOutPainted = nullptr);
322
323
324
325
326

  /**
   * Check whether the given element has a critical display port.
   */
  static bool HasCriticalDisplayPort(nsIContent* aContent);
327

328
  /**
329
330
   * If low-precision painting is turned on, delegates to
   * GetCriticalDisplayPort. Otherwise, delegates to GetDisplayPort.
331
   */
332
  static bool GetHighResolutionDisplayPort(nsIContent* aContent,
333
334
                                           nsRect* aResult,
                                           bool* aOutPainted = nullptr);
335

336
337
338
339
340
  /**
   * Remove the displayport for the given element.
   */
  static void RemoveDisplayPort(nsIContent* aContent);

341
342
343
344
345
346
347
348
349
350
351
352
  /**
   * Notify the scroll frame with the given scroll id that its scroll offset
   * is being sent to APZ as part of a paint-skip transaction.
   *
   * Normally, this notification happens during painting, after calls to
   * ComputeScrollMetadata(). During paint-skipping that code is skipped,
   * but it's still important for the scroll frame to be notified for
   * correctness of relative scroll updates, so the code that sends the
   * empty paint-skip transaction needs to call this.
   */
  static void NotifyPaintSkipTransaction(ViewID aScrollId);

353
  /**
354
   * Use heuristics to figure out the child list that
355
   * aChildFrame is currently in.
356
   */
357
358
  static mozilla::layout::FrameChildListID GetChildListNameFor(
      nsIFrame* aChildFrame);
359

360
  /**
361
   * Returns the ::before pseudo-element for aContent, if any.
362
   */
363
  static mozilla::dom::Element* GetBeforePseudo(const nsIContent* aContent);
364
365

  /**
366
367
   * Returns the frame corresponding to the ::before pseudo-element for
   * aContent, if any.
368
   */
369
  static nsIFrame* GetBeforeFrame(const nsIContent* aContent);
370
371

  /**
372
   * Returns the ::after pseudo-element for aContent, if any.
373
   */
374
  static mozilla::dom::Element* GetAfterPseudo(const nsIContent* aContent);
375
376

  /**
377
378
   * Returns the frame corresponding to the ::after pseudo-element for aContent,
   * if any.
379
   */
380
  static nsIFrame* GetAfterFrame(const nsIContent* aContent);
381

382
383
384
385
386
387
388
389
390
391
392
  /**
   * Returns the ::marker pseudo-element for aContent, if any.
   */
  static mozilla::dom::Element* GetMarkerPseudo(const nsIContent* aContent);

  /**
   * Returns the frame corresponding to the ::marker pseudo-element for
   * aContent, if any.
   */
  static nsIFrame* GetMarkerFrame(const nsIContent* aContent);

393
  /**
394
   * Given a frame, search up the frame tree until we find an
395
   * ancestor that (or the frame itself) is of type aFrameType, if any.
396
   *
397
398
   * @param aFrame the frame to start at
   * @param aFrameType the frame type to look for
399
   * @param aStopAt a frame to stop at after we checked it
400
   * @return a frame of the given type or nullptr if no
401
402
   *         such ancestor exists
   */
403
  static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame,
404
                                         mozilla::LayoutFrameType aFrameType,
405
                                         nsIFrame* aStopAt = nullptr);
406

407
  /**
408
409
410
411
   * Given a frame, search up the frame tree until we find an
   * ancestor that (or the frame itself) is a "Page" frame, if any.
   *
   * @param aFrame the frame to start at
412
   * @return a frame of type mozilla::LayoutFrameType::Page or nullptr if no
413
   *         such ancestor exists
414
   */
415
  static nsIFrame* GetPageFrame(nsIFrame* aFrame);
416

417
418
  /**
   * Given a frame which is the primary frame for an element,
419
   * return the frame that has the non-pseudoelement ComputedStyle for
420
   * the content.
421
   * This is aPrimaryFrame itself except for tableWrapper frames.
422
423
   *
   * Given a non-null input, this will return null if and only if its
424
   * argument is a table wrapper frame that is mid-destruction (and its
425
   * table frame has been destroyed).
426
427
   */
  static nsIFrame* GetStyleFrame(nsIFrame* aPrimaryFrame);
428
  static const nsIFrame* GetStyleFrame(const nsIFrame* aPrimaryFrame);
429

430
431
  /**
   * Given a content node,
432
   * return the frame that has the non-pseudoelement ComputedStyle for
433
   * the content.  May return null.
434
   * This is aContent->GetPrimaryFrame() except for tableWrapper frames.
435
436
437
   */
  static nsIFrame* GetStyleFrame(const nsIContent* aContent);

438
439
440
441
442
  /**
   * The inverse of GetStyleFrame. Returns |aStyleFrame| unless it is an inner
   * table frame, in which case the table wrapper frame is returned.
   */
  static nsIFrame* GetPrimaryFrameFromStyleFrame(nsIFrame* aStyleFrame);
443
444
  static const nsIFrame* GetPrimaryFrameFromStyleFrame(
      const nsIFrame* aStyleFrame);
445

446
447
448
449
450
451
  /**
   * Similar to nsIFrame::IsPrimaryFrame except that this will return true
   * for the inner table frame rather than for its wrapper frame.
   */
  static bool IsPrimaryStyleFrame(const nsIFrame* aFrame);

452
453
454
#ifdef DEBUG
  // TODO: remove, see bug 598468.
  static bool gPreventAssertInCompareTreePosition;
455
#endif  // DEBUG
456

457
  /**
458
459
   * CompareTreePosition determines whether aContent1 comes before or
   * after aContent2 in a preorder traversal of the content tree.
460
   *
461
462
463
464
465
466
467
468
469
470
   * @param aCommonAncestor either null, or a common ancestor of
   *                        aContent1 and aContent2.  Actually this is
   *                        only a hint; if it's not an ancestor of
   *                        aContent1 or aContent2, this function will
   *                        still work, but it will be slower than
   *                        normal.
   * @return < 0 if aContent1 is before aContent2
   *         > 0 if aContent1 is after aContent2,
   *         0 otherwise (meaning they're the same, or they're in
   *           different documents)
471
   */
472
473
474
  static int32_t CompareTreePosition(
      nsIContent* aContent1, nsIContent* aContent2,
      const nsIContent* aCommonAncestor = nullptr) {
475
476
477
478
479
480
481
482
483
    return DoCompareTreePosition(aContent1, aContent2, -1, 1, aCommonAncestor);
  }

  /*
   * More generic version of |CompareTreePosition|.  |aIf1Ancestor|
   * gives the value to return when 1 is an ancestor of 2, and likewise
   * for |aIf2Ancestor|.  Passing (-1, 1) gives preorder traversal
   * order, and (1, -1) gives postorder traversal order.
   */
484
485
486
  static int32_t DoCompareTreePosition(
      nsIContent* aContent1, nsIContent* aContent2, int32_t aIf1Ancestor,
      int32_t aIf2Ancestor, const nsIContent* aCommonAncestor = nullptr);
487
488
489
490
491
492
493
494

  /**
   * CompareTreePosition determines whether aFrame1 comes before or
   * after aFrame2 in a preorder traversal of the frame tree, where out
   * of flow frames are treated as children of their placeholders. This is
   * basically the same ordering as DoCompareTreePosition(nsIContent*) except
   * that it handles anonymous content properly and there are subtleties with
   * continuations.
495
   *
496
497
498
499
500
501
502
503
504
505
506
   * @param aCommonAncestor either null, or a common ancestor of
   *                        aContent1 and aContent2.  Actually this is
   *                        only a hint; if it's not an ancestor of
   *                        aContent1 or aContent2, this function will
   *                        still work, but it will be slower than
   *                        normal.
   * @return < 0 if aContent1 is before aContent2
   *         > 0 if aContent1 is after aContent2,
   *         0 otherwise (meaning they're the same, or they're in
   *           different frame trees)
   */
507
508
  static int32_t CompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
                                     nsIFrame* aCommonAncestor = nullptr) {
509
510
511
    return DoCompareTreePosition(aFrame1, aFrame2, -1, 1, aCommonAncestor);
  }

512
  static int32_t CompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
513
                                     nsTArray<nsIFrame*>& aFrame2Ancestors,
514
515
516
                                     nsIFrame* aCommonAncestor = nullptr) {
    return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors, -1, 1,
                                 aCommonAncestor);
517
518
  }

519
520
521
522
523
524
  /*
   * More generic version of |CompareTreePosition|.  |aIf1Ancestor|
   * gives the value to return when 1 is an ancestor of 2, and likewise
   * for |aIf2Ancestor|.  Passing (-1, 1) gives preorder traversal
   * order, and (1, -1) gives postorder traversal order.
   */
525
  static int32_t DoCompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
526
527
                                       int32_t aIf1Ancestor,
                                       int32_t aIf2Ancestor,
528
                                       nsIFrame* aCommonAncestor = nullptr);
529

530
  static nsIFrame* FillAncestors(nsIFrame* aFrame, nsIFrame* aStopAtAncestor,
531
532
                                 nsTArray<nsIFrame*>* aAncestors);

533
  static int32_t DoCompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
534
535
536
537
538
                                       nsTArray<nsIFrame*>& aFrame2Ancestors,
                                       int32_t aIf1Ancestor,
                                       int32_t aIf2Ancestor,
                                       nsIFrame* aCommonAncestor);

539
  /**
540
   * LastContinuationWithChild gets the last continuation in aFrame's chain
541
542
   * that has a child, or the first continuation if the frame has no children.
   */
543
  static nsContainerFrame* LastContinuationWithChild(nsContainerFrame* aFrame);
544

545
  /**
546
547
   * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr
   * if aFrame is null.
548
549
550
551
552
553
554
555
556
557
   */
  static nsIFrame* GetLastSibling(nsIFrame* aFrame);

  /**
   * FindSiblingViewFor locates the child of aParentView that aFrame's
   * view should be inserted 'above' (i.e., before in sibling view
   * order).  This is the first child view of aParentView whose
   * corresponding content is before aFrame's content (view siblings
   * are in reverse content order).
   */
558
  static nsView* FindSiblingViewFor(nsView* aParentView, nsIFrame* aFrame);
559

560
561
562
563
  /**
   * Get the parent of aFrame. If aFrame is the root frame for a document,
   * and the document has a parent document in the same view hierarchy, then
   * we try to return the subdocumentframe in the parent document.
564
   * @param aExtraOffset [in/out] if non-null, then as we cross documents
Timothy Nikkel's avatar
Timothy Nikkel committed
565
566
567
568
   * an extra offset may be required and it will be added to aCrossDocOffset.
   * Be careful dealing with this extra offset as it is in app units of the
   * parent document, which may have a different app units per dev pixel ratio
   * than the child document.
569
   */
570
  static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame,
571
                                          nsPoint* aCrossDocOffset = nullptr);
572

573
574
575
  /**
   * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor
   * of aFrame and not equal to aFrame.
576
   * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
577
578
579
   * aAncestorFrame. If non-null, this can bound the search and speed up
   * the function
   */
580
581
582
  static bool IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
                                    const nsIFrame* aFrame,
                                    const nsIFrame* aCommonAncestor = nullptr);
583

584
585
  /**
   * Like IsProperAncestorFrame, but looks across document boundaries.
586
587
588
   *
   * Just like IsAncestorFrameCrossDoc, except that it returns false when
   * aFrame == aAncestorFrame.
589
   */
590
  static bool IsProperAncestorFrameCrossDoc(
591
592
      const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
      const nsIFrame* aCommonAncestor = nullptr);
593

594
595
596
  /**
   * IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor
   * of aFrame or equal to aFrame, looking across document boundaries.
597
   * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
598
599
600
601
602
603
   * aAncestorFrame. If non-null, this can bound the search and speed up
   * the function.
   *
   * Just like IsProperAncestorFrameCrossDoc, except that it returns true when
   * aFrame == aAncestorFrame.
   */
604
605
606
  static bool IsAncestorFrameCrossDoc(
      const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
      const nsIFrame* aCommonAncestor = nullptr);
607

608
609
  /**
   * Sets the fixed-pos metadata properties on aLayer.
610
611
612
613
   * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a
   * viewport frame, then we pick a corner of aAnchorRect to as the anchor point
   * for the fixed-pos layer (i.e. the point to remain stable during zooming),
   * based on which of the fixed-pos frame's CSS absolute positioning offset
614
   * properties (top, left, right, bottom) are auto. aAnchorRect is in the
615
616
617
   * coordinate space of aLayer's container layer (i.e. relative to the
   * reference frame of the display item which is building aLayer's container
   * layer).
618
   */
619
620
621
622
  static void SetFixedPositionLayerData(
      Layer* aLayer, const nsIFrame* aViewportFrame, const nsRect& aAnchorRect,
      const nsIFrame* aFixedPosFrame, nsPresContext* aPresContext,
      const ContainerLayerParameters& aContainerParameters);
623

624
625
626
627
628
629
  static mozilla::SideBits GetSideBitsAndAdjustAnchorForFixedPositionContent(
      const nsIFrame* aViewportFrame, const nsIFrame* aFixedPosFrame,
      mozilla::LayerPoint* aAnchor, const Rect* aAnchorRect);
  static mozilla::SideBits GetSideBitsForFixedPositionContent(
      const nsIFrame* aFixedPosFrame);

630
631
632
633
  /**
   * Get the scroll id for the root scrollframe of the presshell of the given
   * prescontext. Returns NULL_SCROLL_ID if it couldn't be found.
   */
634
  static ViewID ScrollIdForRootScrollFrame(nsPresContext* aPresContext);
635

636
637
638
  /**
   * Return true if aPresContext's viewport has a displayport.
   */
639
  static bool ViewportHasDisplayPort(nsPresContext* aPresContext);
640

641
642
  /**
   * Return true if aFrame is a fixed-pos frame and is a child of a viewport
643
644
645
   * which has a displayport. These frames get special treatment from the
   * compositor. aDisplayPort, if non-null, is set to the display port rectangle
   * (relative to the viewport).
646
   */
647
  static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame);
648

649
  /**
650
651
652
653
   * GetScrollableFrameFor returns the scrollable frame for a scrolled frame
   */
  static nsIScrollableFrame* GetScrollableFrameFor(
      const nsIFrame* aScrolledFrame);
654

655
  /**
656
657
658
659
660
661
   * GetNearestScrollableFrameForDirection locates the first ancestor of
   * aFrame (or aFrame itself) that is scrollable with overflow:scroll or
   * overflow:auto in the given direction and where either the scrollbar for
   * that direction is visible or the frame can be scrolled by some
   * positive amount in that direction.
   * The search extends across document boundaries.
662
   *
663
   * @param  aFrame the frame to start with
664
   * @param  aDirection Whether it's for horizontal or vertical scrolling.
665
   * @return the nearest scrollable frame or nullptr if not found
666
667
   */
  enum Direction { eHorizontal, eVertical };
668
669
  static nsIScrollableFrame* GetNearestScrollableFrameForDirection(
      nsIFrame* aFrame, Direction aDirection);
670

671
  enum {
672
673
674
675
    /**
     * If the SCROLLABLE_SAME_DOC flag is set, then we only walk the frame tree
     * up to the root frame in the current document.
     */
676
    SCROLLABLE_SAME_DOC = 0x01,
677
678
679
680
681
682
683
684
685
686
687
688
    /**
     * If the SCROLLABLE_INCLUDE_HIDDEN flag is set then we allow
     * overflow:hidden scrollframes to be returned as scrollable frames.
     */
    SCROLLABLE_INCLUDE_HIDDEN = 0x02,
    /**
     * If the SCROLLABLE_ONLY_ASYNC_SCROLLABLE flag is set, then we only
     * want to match scrollable frames for which WantAsyncScroll() returns
     * true.
     */
    SCROLLABLE_ONLY_ASYNC_SCROLLABLE = 0x04,
    /**
689
690
691
692
     * If the SCROLLABLE_ALWAYS_MATCH_ROOT flag is set, then we will always
     * return the root scrollable frame for the root document (in the current
     * process) if we encounter it, whether or not it is async scrollable or
     * overflow: hidden.
693
694
     */
    SCROLLABLE_ALWAYS_MATCH_ROOT = 0x08,
695
696
    /**
     * If the SCROLLABLE_FIXEDPOS_FINDS_ROOT flag is set, then for fixed-pos
697
     * frames return the root scrollable frame for that document.
698
     */
699
700
701
702
703
704
705
706
    SCROLLABLE_FIXEDPOS_FINDS_ROOT = 0x10,
    /**
     * If the SCROLLABLE_STOP_AT_PAGE flag is set, then we stop searching
     * for scrollable ancestors when seeing a nsPageFrame.  This can be used
     * to avoid finding the viewport scroll frame in Print Preview (which
     * would be undesirable as a 'position:sticky' container for content).
     */
    SCROLLABLE_STOP_AT_PAGE = 0x20,
707
  };
708
709
710
711
712
713
  /**
   * GetNearestScrollableFrame locates the first ancestor of aFrame
   * (or aFrame itself) that is scrollable with overflow:scroll or
   * overflow:auto in some direction.
   *
   * @param  aFrame the frame to start with
714
715
716
   * @param  aFlags if SCROLLABLE_SAME_DOC is set, do not search across
   * document boundaries. If SCROLLABLE_INCLUDE_HIDDEN is set, include
   * frames scrollable with overflow:hidden.
717
   * @return the nearest scrollable frame or nullptr if not found
718
   */
719
720
  static nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame,
                                                       uint32_t aFlags = 0);
721

722
723
724
725
726
727
728
729
  /**
   * GetScrolledRect returns the range of allowable scroll offsets
   * for aScrolledFrame, assuming the scrollable overflow area is
   * aScrolledFrameOverflowArea and the scrollport size is aScrollPortSize.
   */
  static nsRect GetScrolledRect(nsIFrame* aScrolledFrame,
                                const nsRect& aScrolledFrameOverflowArea,
                                const nsSize& aScrollPortSize,
730
                                mozilla::StyleDirection);
731

732
  /**
733
   * HasPseudoStyle returns true if aContent (whose primary style
734
   * context is aComputedStyle) has the aPseudoElement pseudo-style
735
   * attached to it; returns false otherwise.
736
737
   *
   * @param aContent the content node we're looking at
738
   * @param aComputedStyle aContent's ComputedStyle
739
   * @param aPseudoElement the id of the pseudo style we care about
740
741
742
   * @param aPresContext the presentation context
   * @return whether aContent has aPseudoElement style attached to it
   */
743
  static bool HasPseudoStyle(nsIContent* aContent,
744
                             ComputedStyle* aComputedStyle,
745
                             mozilla::PseudoStyleType aPseudoElement,
746
                             nsPresContext* aPresContext);
747
748
749

  /**
   * If this frame is a placeholder for a float, then return the float,
750
   * otherwise return nullptr.  aPlaceholder must be a placeholder frame.
751
   */
752
  static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPlaceholder);
753
754

  // Combine aNewBreakType with aOrigBreakType, but limit the break types
755
  // to StyleClear::Left, Right, Both.
756
757
  static mozilla::StyleClear CombineBreakType(
      mozilla::StyleClear aOrigBreakType, mozilla::StyleClear aNewBreakType);
758

759
760
  /**
   * Get the coordinates of a given DOM mouse event, relative to a given
761
   * frame. Works only for DOM events generated by WidgetGUIEvents.
762
763
764
765
766
767
   * @param aDOMEvent the event
   * @param aFrame the frame to make coordinates relative to
   * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
   * for some reason the coordinates for the mouse are not known (e.g.,
   * the event is not a GUI event).
   */
768
769
  static nsPoint GetDOMEventCoordinatesRelativeTo(
      mozilla::dom::Event* aDOMEvent, nsIFrame* aFrame);
770
771
772
773
774
775
776
777
778
779

  /**
   * Get the coordinates of a given native mouse event, relative to a given
   * frame.
   * @param aEvent the event
   * @param aFrame the frame to make coordinates relative to
   * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
   * for some reason the coordinates for the mouse are not known (e.g.,
   * the event is not a GUI event).
   */
780
  static nsPoint GetEventCoordinatesRelativeTo(
781
      const mozilla::WidgetEvent* aEvent, RelativeTo aFrame);
782

783
784
785
786
787
788
789
790
791
792
  /**
   * Get the coordinates of a given point relative to an event and a
   * given frame.
   * @param aEvent the event
   * @param aPoint the point to get the coordinates relative to
   * @param aFrame the frame to make coordinates relative to
   * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
   * for some reason the coordinates for the mouse are not known (e.g.,
   * the event is not a GUI event).
   */
793
  static nsPoint GetEventCoordinatesRelativeTo(
794
      const mozilla::WidgetEvent* aEvent,
795
      const mozilla::LayoutDeviceIntPoint& aPoint, RelativeTo aFrame);
796

797
798
799
800
801
802
803
804
805
806
  /**
   * Get the coordinates of a given point relative to a widget and a
   * given frame.
   * @param aWidget the event src widget
   * @param aPoint the point to get the coordinates relative to
   * @param aFrame the frame to make coordinates relative to
   * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
   * for some reason the coordinates for the mouse are not known (e.g.,
   * the event is not a GUI event).
   */
807
808
  static nsPoint GetEventCoordinatesRelativeTo(
      nsIWidget* aWidget, const mozilla::LayoutDeviceIntPoint& aPoint,
809
      RelativeTo aFrame);
810

811
  /**
812
   * Get the popup frame of a given native mouse event.
813
   * @param aPresContext only check popups within aPresContext or a descendant
814
815
816
817
   * @param aEvent  the event.
   * @return        Null, if there is no popup frame at the point, otherwise,
   *                returns top-most popup frame at the point.
   */
818
  static nsIFrame* GetPopupFrameForEventCoordinates(
819
      nsPresContext* aPresContext, const mozilla::WidgetEvent* aEvent);
820

821
822
823
824
825
826
827
828
829
830
831
  /**
   * Get container and offset if aEvent collapses Selection.
   * @param aPresShell      The PresShell handling aEvent.
   * @param aEvent          The event having coordinates where you want to
   *                        collapse Selection.
   * @param aContainer      Returns the container node at the point.
   *                        Set nullptr if you don't need this.
   * @param aOffset         Returns offset in the container node at the point.
   *                        Set nullptr if you don't need this.
   */
  MOZ_CAN_RUN_SCRIPT
832
  static void GetContainerAndOffsetAtEvent(PresShell* aPresShell,
833
834
835
836
                                           const mozilla::WidgetEvent* aEvent,
                                           nsIContent** aContainer,
                                           int32_t* aOffset);

837
  /**
838
839
840
841
842
843
844
   * Translate from widget coordinates to the view's coordinates
   * @param aPresContext the PresContext for the view
   * @param aWidget the widget
   * @param aPt the point relative to the widget
   * @param aView  view to which returned coordinates are relative
   * @return the point in the view's coordinates
   */
845
  static nsPoint TranslateWidgetToView(nsPresContext* aPresContext,
846
847
                                       nsIWidget* aWidget,
                                       const mozilla::LayoutDeviceIntPoint& aPt,
848
                                       nsView* aView);
849

850
851
852
853
854
  /**
   * Translate from view coordinates to the widget's coordinates.
   * @param aPresContext the PresContext for the view
   * @param aView the view
   * @param aPt the point relative to the view
855
   * @param aViewportType whether the point is in visual or layout coordinates
856
857
858
   * @param aWidget the widget to which returned coordinates are relative
   * @return the point in the view's coordinates
   */
859
860
  static mozilla::LayoutDeviceIntPoint TranslateViewToWidget(
      nsPresContext* aPresContext, nsView* aView, nsPoint aPt,
861
      ViewportType aViewportType, nsIWidget* aWidget);
862

863
864
  static mozilla::LayoutDeviceIntPoint WidgetToWidgetOffset(
      nsIWidget* aFromWidget, nsIWidget* aToWidget);
865

866
  enum class FrameForPointOption {
867
868
869
870
    /**
     * When set, paint suppression is ignored, so we'll return non-root page
     * elements even if paint suppression is stopping them from painting.