68.14.6 - layout - servo

This commit is contained in:
Fedor 2025-01-22 01:25:03 +02:00
parent 241983a236
commit d3ff103fd5
1320 changed files with 51438 additions and 26719 deletions

View File

@ -14,6 +14,7 @@
#include "nsCSSFrameConstructor.h"
#include "nsDOMTokenList.h"
#include "nsIFrame.h"
#include "nsLayoutUtils.h"
#include "nsPlaceholderFrame.h"
namespace mozilla {
@ -29,8 +30,9 @@ using namespace dom;
NS_IMPL_ISUPPORTS(AccessibleCaret::DummyTouchListener, nsIDOMEventListener)
NS_NAMED_LITERAL_STRING(AccessibleCaret::sTextOverlayElementId, "text-overlay");
NS_NAMED_LITERAL_STRING(AccessibleCaret::sCaretImageElementId, "image");
const nsLiteralString AccessibleCaret::sTextOverlayElementId =
u"text-overlay"_ns;
const nsLiteralString AccessibleCaret::sCaretImageElementId = u"image"_ns;
#define AC_PROCESS_ENUM_TO_STREAM(e) \
case (e): \
@ -111,16 +113,16 @@ nsAutoString AccessibleCaret::AppearanceString(Appearance aAppearance) {
switch (aAppearance) {
case Appearance::None:
case Appearance::NormalNotShown:
string = NS_LITERAL_STRING("none");
string = u"none"_ns;
break;
case Appearance::Normal:
string = NS_LITERAL_STRING("normal");
string = u"normal"_ns;
break;
case Appearance::Right:
string = NS_LITERAL_STRING("right");
string = u"right"_ns;
break;
case Appearance::Left:
string = NS_LITERAL_STRING("left");
string = u"left"_ns;
break;
}
return string;
@ -165,8 +167,8 @@ void AccessibleCaret::EnsureApzAware() {
// the element already.
if (!CaretElement().IsApzAware()) {
// FIXME(emilio): Is this needed anymore?
CaretElement().AddEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
CaretElement().AddEventListener(u"touchstart"_ns, mDummyTouchListener,
false);
}
}
@ -204,8 +206,8 @@ already_AddRefed<Element> AccessibleCaret::CreateCaretElement(
ErrorResult rv;
RefPtr<Element> parent = aDocument->CreateHTMLElement(nsGkAtoms::div);
parent->ClassList()->Add(NS_LITERAL_STRING("moz-accessiblecaret"), rv);
parent->ClassList()->Add(NS_LITERAL_STRING("none"), rv);
parent->ClassList()->Add(u"moz-accessiblecaret"_ns, rv);
parent->ClassList()->Add(u"none"_ns, rv);
auto CreateAndAppendChildElement =
[aDocument, &parent](const nsLiteralString& aElementId) {
@ -221,8 +223,8 @@ already_AddRefed<Element> AccessibleCaret::CreateCaretElement(
}
void AccessibleCaret::RemoveCaretElement(Document* aDocument) {
CaretElement().RemoveEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
CaretElement().RemoveEventListener(u"touchstart"_ns, mDummyTouchListener,
false);
aDocument->RemoveAnonymousContent(*mCaretElementHolder, IgnoreErrors());
}

View File

@ -10,7 +10,7 @@
#include "mozilla/dom/Element.h"
#include "nsCOMPtr.h"
#include "nsIDOMEventListener.h"
#include "nsIFrame.h"
#include "nsIFrame.h" // for WeakFrame only
#include "nsISupportsBase.h"
#include "nsISupportsImpl.h"
#include "nsLiteralString.h"

View File

@ -23,6 +23,7 @@
#include "nsFocusManager.h"
#include "nsFrameSelection.h"
#include "nsITimer.h"
#include "nsLayoutUtils.h"
#include "nsPresContext.h"
using namespace mozilla;
@ -686,8 +687,8 @@ nsPoint AccessibleCaretEventHub::GetTouchEventPosition(
// Get event coordinate relative to root frame.
nsIFrame* rootFrame = mPresShell->GetRootFrame();
return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, touchIntPoint,
rootFrame);
return nsLayoutUtils::GetEventCoordinatesRelativeTo(
aEvent, touchIntPoint, RelativeTo{rootFrame});
}
}
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
@ -700,7 +701,7 @@ nsPoint AccessibleCaretEventHub::GetMouseEventPosition(
// Get event coordinate relative to root frame.
nsIFrame* rootFrame = mPresShell->GetRootFrame();
return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, mouseIntPoint,
rootFrame);
RelativeTo{rootFrame});
}
} // namespace mozilla

View File

@ -5,12 +5,12 @@
#ifndef mozilla_AccessibleCaretEventHub_h
#define mozilla_AccessibleCaretEventHub_h
#include "LayoutConstants.h"
#include "mozilla/EventForwards.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "nsCOMPtr.h"
#include "nsDocShell.h"
#include "nsIFrame.h"
#include "nsIReflowObserver.h"
#include "nsIScrollObserver.h"
#include "nsPoint.h"

View File

@ -517,11 +517,6 @@ static EnumSet<nsLayoutUtils::FrameForPointOption> GetHitTestOptions() {
EnumSet<nsLayoutUtils::FrameForPointOption> options = {
nsLayoutUtils::FrameForPointOption::IgnorePaintSuppression,
nsLayoutUtils::FrameForPointOption::IgnoreCrossDoc};
#ifdef MOZ_WIDGET_ANDROID
// On Android, we need IgnoreRootScrollFrame for correct hit testing when
// zoomed in or out.
options += nsLayoutUtils::FrameForPointOption::IgnoreRootScrollFrame;
#endif
return options;
}
@ -547,8 +542,8 @@ nsresult AccessibleCaretManager::SelectWordOrShortcut(const nsPoint& aPoint) {
}
// Find the frame under point.
AutoWeakFrame ptFrame =
nsLayoutUtils::GetFrameForPoint(rootFrame, aPoint, GetHitTestOptions());
AutoWeakFrame ptFrame = nsLayoutUtils::GetFrameForPoint(
RelativeTo{rootFrame}, aPoint, GetHitTestOptions());
if (!ptFrame.GetFrame()) {
return NS_ERROR_FAILURE;
}
@ -568,7 +563,8 @@ nsresult AccessibleCaretManager::SelectWordOrShortcut(const nsPoint& aPoint) {
// something under the original point will be selected, which may not be the
// original text the user wants to select.
nsPoint ptInFrame = aPoint;
nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame);
nsLayoutUtils::TransformPoint(RelativeTo{rootFrame}, RelativeTo{ptFrame},
ptInFrame);
// Firstly check long press on an empty editable content.
Element* newFocusEditingHost = GetEditingHostForFrame(ptFrame);
@ -927,8 +923,7 @@ void AccessibleCaretManager::SetSelectionDragState(bool aState) const {
bool AccessibleCaretManager::IsPhoneNumber(nsAString& aCandidate) const {
RefPtr<Document> doc = mPresShell->GetDocument();
nsAutoString phoneNumberRegex(
NS_LITERAL_STRING("(^\\+)?[0-9 ,\\-.()*#pw]{1,30}$"));
nsAutoString phoneNumberRegex(u"(^\\+)?[0-9 ,\\-.()*#pw]{1,30}$"_ns);
return nsContentUtils::IsPatternMatching(aCandidate, phoneNumberRegex, doc)
.valueOr(false);
}
@ -938,10 +933,10 @@ void AccessibleCaretManager::SelectMoreIfPhoneNumber() const {
if (IsPhoneNumber(selectedText)) {
SetSelectionDirection(eDirNext);
ExtendPhoneNumberSelection(NS_LITERAL_STRING("forward"));
ExtendPhoneNumberSelection(u"forward"_ns);
SetSelectionDirection(eDirPrevious);
ExtendPhoneNumberSelection(NS_LITERAL_STRING("backward"));
ExtendPhoneNumberSelection(u"backward"_ns);
SetSelectionDirection(eDirNext);
}
@ -973,8 +968,8 @@ void AccessibleCaretManager::ExtendPhoneNumberSelection(
nsAutoString oldSelectedText = StringifiedSelection();
// Extend the selection by one char.
selection->Modify(NS_LITERAL_STRING("extend"), aDirection,
NS_LITERAL_STRING("character"), IgnoreErrors());
selection->Modify(u"extend"_ns, aDirection, u"character"_ns,
IgnoreErrors());
if (IsTerminated()) {
return;
}
@ -1218,8 +1213,8 @@ nsresult AccessibleCaretManager::DragCaretInternal(const nsPoint& aPoint) {
// Find out which content we point to
nsIFrame* ptFrame =
nsLayoutUtils::GetFrameForPoint(rootFrame, point, GetHitTestOptions());
nsIFrame* ptFrame = nsLayoutUtils::GetFrameForPoint(
RelativeTo{rootFrame}, point, GetHitTestOptions());
if (!ptFrame) {
return NS_ERROR_FAILURE;
}
@ -1231,7 +1226,8 @@ nsresult AccessibleCaretManager::DragCaretInternal(const nsPoint& aPoint) {
nsIFrame* newFrame = nullptr;
nsPoint newPoint;
nsPoint ptInFrame = point;
nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame);
nsLayoutUtils::TransformPoint(RelativeTo{rootFrame}, RelativeTo{ptFrame},
ptInFrame);
result = fs->ConstrainFrameAndPointToAnchorSubtree(ptFrame, ptInFrame,
&newFrame, newPoint);
if (NS_FAILED(result) || !newFrame) {
@ -1277,7 +1273,7 @@ nsRect AccessibleCaretManager::GetAllChildFrameRectsUnion(
for (const auto& childList : frame->ChildLists()) {
// Loop all children to union their scrollable overflow rect.
for (nsIFrame* child : childList.mList) {
nsRect childRect = child->GetScrollableOverflowRectRelativeToSelf();
nsRect childRect = child->ScrollableOverflowRectRelativeToSelf();
nsLayoutUtils::TransformRect(child, frame, childRect);
// A TextFrame containing only '\n' has positive height and width 0, or
@ -1379,7 +1375,8 @@ void AccessibleCaretManager::StartSelectionAutoScrollTimer(
nsIFrame* rootFrame = mPresShell->GetRootFrame();
MOZ_ASSERT(rootFrame);
nsPoint ptInScrolled = aPoint;
nsLayoutUtils::TransformPoint(rootFrame, capturingFrame, ptInScrolled);
nsLayoutUtils::TransformPoint(RelativeTo{rootFrame},
RelativeTo{capturingFrame}, ptInScrolled);
RefPtr<nsFrameSelection> fs = GetFrameSelection();
MOZ_ASSERT(fs);
@ -1463,7 +1460,7 @@ void AccessibleCaretManager::DispatchCaretStateChangedEvent(
init.mSelectedTextContent = StringifiedSelection();
RefPtr<CaretStateChangedEvent> event = CaretStateChangedEvent::Constructor(
doc, NS_LITERAL_STRING("mozcaretstatechanged"), init);
doc, u"mozcaretstatechanged"_ns, init);
event->SetTrusted(true);
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
/* 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/. */
#ifndef mozilla_DisplayPortUtils_h__
#define mozilla_DisplayPortUtils_h__
#include "Units.h"
#include "nsDisplayList.h"
#include "nsRect.h"
#include <cstdint>
#include <iosfwd>
class nsIContent;
class nsIFrame;
class nsDisplayListBuilder;
class nsPresContext;
namespace mozilla {
class PresShell;
// For GetDisplayPort
enum class DisplayportRelativeTo { ScrollPort, ScrollFrame };
enum class MaxSizeExceededBehaviour {
// Ask GetDisplayPort to assert if the calculated displayport exceeds
// the maximum allowed size.
Assert,
// Ask GetDisplayPort to pretend like there's no displayport at all, if
// the calculated displayport exceeds the maximum allowed size.
Drop,
};
// Is the displayport being applied to scrolled content or fixed content?
enum class ContentGeometryType { Scrolled, Fixed };
struct DisplayPortOptions {
// The default options.
DisplayportRelativeTo mRelativeTo = DisplayportRelativeTo::ScrollPort;
MaxSizeExceededBehaviour mMaxSizeExceededBehaviour =
MaxSizeExceededBehaviour::Assert;
ContentGeometryType mGeometryType = ContentGeometryType::Scrolled;
// Fluent interface for changing the defaults.
DisplayPortOptions With(DisplayportRelativeTo aRelativeTo) const {
DisplayPortOptions result = *this;
result.mRelativeTo = aRelativeTo;
return result;
}
DisplayPortOptions With(
MaxSizeExceededBehaviour aMaxSizeExceededBehaviour) const {
DisplayPortOptions result = *this;
result.mMaxSizeExceededBehaviour = aMaxSizeExceededBehaviour;
return result;
}
DisplayPortOptions With(ContentGeometryType aGeometryType) const {
DisplayPortOptions result = *this;
result.mGeometryType = aGeometryType;
return result;
}
};
struct DisplayPortPropertyData {
DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority,
bool aPainted)
: mRect(aRect), mPriority(aPriority), mPainted(aPainted) {}
nsRect mRect;
uint32_t mPriority;
bool mPainted;
};
struct DisplayPortMargins {
// The margins relative to the visual scroll offset.
ScreenMargin mMargins;
// Some information captured at the time the margins are stored.
// This ensures that we can express the margins as being relative to
// the correct scroll offset when applying them.
// APZ's visual scroll offset at the time it requested the margins.
CSSPoint mVisualOffset;
// The scroll frame's layout scroll offset at the time the margins
// were saved.
CSSPoint mLayoutOffset;
// The scale required to convert between the CSS cordinates of
// mVisualOffset and mLayoutOffset, and the Screen coordinates of mMargins.
CSSToScreenScale2D mScale;
static DisplayPortMargins WithAdjustment(const ScreenMargin& aMargins,
const CSSPoint& aVisualOffset,
const CSSPoint& aLayoutOffset,
const CSSToScreenScale2D& aScale);
static DisplayPortMargins WithNoAdjustment(const ScreenMargin& aMargins);
static DisplayPortMargins Empty() { return WithNoAdjustment(ScreenMargin()); }
// Get the margins relative to the layout viewport.
// |aGeometryType| tells us whether the margins are being queried for the
// purpose of being applied to scrolled content or fixed content.
// |aScrollableFrame| is the scroll frame whose content the margins will be
// applied to (or, in the case of fixed content), the scroll frame wrt. which
// the content is fixed.
ScreenMargin GetRelativeToLayoutViewport(
ContentGeometryType aGeometryType,
nsIScrollableFrame* aScrollableFrame) const;
friend std::ostream& operator<<(std::ostream& aOs,
const DisplayPortMargins& aMargins);
private:
CSSPoint ComputeAsyncTranslation(ContentGeometryType aGeometryType,
nsIScrollableFrame* aScrollableFrame) const;
};
struct DisplayPortMarginsPropertyData {
DisplayPortMarginsPropertyData(const DisplayPortMargins& aMargins,
uint32_t aPriority, bool aPainted)
: mMargins(aMargins), mPriority(aPriority), mPainted(aPainted) {}
DisplayPortMargins mMargins;
uint32_t mPriority;
bool mPainted;
};
class DisplayPortUtils {
public:
/**
* Get display port for the given element, relative to the specified entity,
* defaulting to the scrollport.
*/
static bool GetDisplayPort(
nsIContent* aContent, nsRect* aResult,
const DisplayPortOptions& aOptions = DisplayPortOptions());
/**
* Check whether the given element has a displayport.
*/
static bool HasDisplayPort(nsIContent* aContent);
/**
* 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);
/**
* 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.
*/
static bool FrameHasDisplayPort(nsIFrame* aFrame,
const nsIFrame* aScrolledFrame = nullptr);
/**
* 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);
/**
* 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();
/**
* @return the display port for the given element which should be used for
* visibility testing purposes, relative to the scroll frame.
*
* If low-precision buffers are enabled, this is the critical display port;
* otherwise, it's the same display port returned by GetDisplayPort().
*/
static bool GetDisplayPortForVisibilityTesting(nsIContent* aContent,
nsRect* aResult);
enum class RepaintMode : uint8_t { Repaint, DoNotRepaint };
/**
* Invalidate for displayport change.
*/
static void InvalidateForDisplayPortChange(
nsIContent* aContent, bool aHadDisplayPort, const nsRect& aOldDisplayPort,
const nsRect& aNewDisplayPort,
RepaintMode aRepaintMode = RepaintMode::Repaint);
/**
* 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
* @return true if the new margins were applied.
*/
static bool SetDisplayPortMargins(
nsIContent* aContent, PresShell* aPresShell,
const DisplayPortMargins& aMargins, uint32_t aPriority = 0,
RepaintMode aRepaintMode = RepaintMode::Repaint);
/**
* Set the display port base rect for given element to be used with display
* port margins.
* SetDisplayPortBaseIfNotSet is like SetDisplayPortBase except it only sets
* the display port base to aBase if no display port base is currently set.
*/
static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase);
static void SetDisplayPortBaseIfNotSet(nsIContent* aContent,
const nsRect& aBase);
/**
* Get the critical display port for the given element.
*/
static bool GetCriticalDisplayPort(
nsIContent* aContent, nsRect* aResult,
const DisplayPortOptions& aOptions = DisplayPortOptions());
/**
* Check whether the given element has a critical display port.
*/
static bool HasCriticalDisplayPort(nsIContent* aContent);
/**
* If low-precision painting is turned on, delegates to
* GetCriticalDisplayPort. Otherwise, delegates to GetDisplayPort.
*/
static bool GetHighResolutionDisplayPort(
nsIContent* aContent, nsRect* aResult,
const DisplayPortOptions& aOptions = DisplayPortOptions());
/**
* Remove the displayport for the given element.
*/
static void RemoveDisplayPort(nsIContent* aContent);
/**
* Return true if aPresContext's viewport has a displayport.
*/
static bool ViewportHasDisplayPort(nsPresContext* aPresContext);
/**
* Return true if aFrame is a fixed-pos frame and is a child of a viewport
* 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).
*/
static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame);
static bool MaybeCreateDisplayPortInFirstScrollFrameEncountered(
nsIFrame* aFrame, nsDisplayListBuilder* aBuilder);
/**
* Calculate a default set of displayport margins for the given scrollframe
* and set them on the scrollframe's content element. The margins are set with
* the default priority, which may clobber previously set margins. The repaint
* mode provided is passed through to the call to SetDisplayPortMargins.
* The |aScrollFrame| parameter must be non-null and queryable to an nsIFrame.
* @return true iff the call to SetDisplayPortMargins returned true.
*/
static bool CalculateAndSetDisplayPortMargins(
nsIScrollableFrame* aScrollFrame, RepaintMode aRepaintMode);
/**
* If |aScrollFrame| WantsAsyncScroll() and we don't have a scrollable
* displayport yet (as tracked by |aBuilder|), calculate and set a
* displayport.
*
* If this is called during display list building pass DoNotRepaint in
* aRepaintMode.
*
* Returns true if there is a displayport on an async scrollable scrollframe
* after this call, either because one was just added or it already existed.
*/
static bool MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
nsIFrame* aScrollFrame,
RepaintMode aRepaintMode);
/**
* Sets a zero margin display port on all proper ancestors of aFrame that
* are async scrollable.
*/
static void SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
nsIFrame* aFrame);
/**
* Finds the closest ancestor async scrollable frame from aFrame that has a
* displayport and attempts to trigger the displayport expiry on that
* ancestor.
*/
static void ExpireDisplayPortOnAsyncScrollableAncestor(nsIFrame* aFrame);
};
} // namespace mozilla
#endif // mozilla_DisplayPortUtils_h__

View File

@ -7,7 +7,6 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Unused.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"

View File

@ -4,9 +4,11 @@
#include "GeckoMVMContext.h"
#include "mozilla/DisplayPortUtils.h"
#include "mozilla/PresShell.h"
#include "mozilla/Services.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/VisualViewport.h"
#include "nsCOMPtr.h"
#include "nsGlobalWindowInner.h"
#include "nsIDOMEventListener.h"
@ -131,7 +133,7 @@ bool GeckoMVMContext::IsInReaderMode() const {
if (NS_FAILED(mDocument->GetDocumentURI(uri))) {
return false;
}
static auto readerModeUriPrefix = NS_LITERAL_STRING("about:reader");
static auto readerModeUriPrefix = u"about:reader"_ns;
return StringBeginsWith(uri, readerModeUriPrefix);
}
@ -154,7 +156,7 @@ void GeckoMVMContext::SetVisualViewportSize(const CSSSize& aSize) {
void GeckoMVMContext::UpdateDisplayPortMargins() {
MOZ_ASSERT(mPresShell);
if (nsIFrame* root = mPresShell->GetRootScrollFrame()) {
bool hasDisplayPort = nsLayoutUtils::HasDisplayPort(root->GetContent());
bool hasDisplayPort = DisplayPortUtils::HasDisplayPort(root->GetContent());
bool hasResolution = mPresShell->GetResolution() != 1.0f;
if (!hasDisplayPort && !hasResolution) {
// We only want to update the displayport if there is one already, or
@ -168,11 +170,11 @@ void GeckoMVMContext::UpdateDisplayPortMargins() {
// ever changes we'd need to limit the size of this displayport base rect
// because non-toplevel documents have no limit on their size.
MOZ_ASSERT(mPresShell->GetPresContext()->IsRootContentDocument());
nsLayoutUtils::SetDisplayPortBaseIfNotSet(root->GetContent(),
displayportBase);
DisplayPortUtils::SetDisplayPortBaseIfNotSet(root->GetContent(),
displayportBase);
nsIScrollableFrame* scrollable = do_QueryFrame(root);
nsLayoutUtils::CalculateAndSetDisplayPortMargins(
scrollable, nsLayoutUtils::RepaintMode::Repaint);
DisplayPortUtils::CalculateAndSetDisplayPortMargins(
scrollable, DisplayPortUtils::RepaintMode::Repaint);
}
}

View File

@ -5,6 +5,7 @@
#include "GeometryUtils.h"
#include "mozilla/PresShell.h"
#include "mozilla/SVGUtils.h"
#include "mozilla/dom/CharacterData.h"
#include "mozilla/dom/DOMPointBinding.h"
#include "mozilla/dom/GeometryUtilsBinding.h"
@ -16,7 +17,6 @@
#include "nsIFrame.h"
#include "nsCSSFrameConstructor.h"
#include "nsLayoutUtils.h"
#include "nsSVGUtils.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -140,7 +140,7 @@ static nsIFrame* GetFirstNonAnonymousFrameForNode(nsINode* aNode) {
*/
static nsRect GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType) {
nsRect r;
nsIFrame* f = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(*aFrame, &r);
nsIFrame* f = SVGUtils::GetOuterSVGFrameAndCoveredRegion(*aFrame, &r);
if (f && f != *aFrame) {
// For non-outer SVG frames, the BoxType is ignored.
*aFrame = f;

View File

@ -7,7 +7,9 @@
#ifndef LayoutConstants_h___
#define LayoutConstants_h___
#include "mozilla/EnumSet.h"
#include "nsSize.h" // for NS_MAXSIZE
#include "Units.h"
/**
* Constant used to indicate an unconstrained size.
@ -26,4 +28,71 @@
#define NS_INTRINSIC_ISIZE_UNKNOWN nscoord_MIN
namespace mozilla {
/**
* Bit-flags to pass to various functions that compute sizes like
* nsIFrame::ComputeSize().
*/
enum class ComputeSizeFlag : uint8_t {
/**
* Set if the frame is in a context where non-replaced blocks should
* shrink-wrap (e.g., it's floating, absolutely positioned, or
* inline-block).
*/
ShrinkWrap,
/**
* Set if we'd like to compute our 'auto' bsize, regardless of our actual
* corresponding computed value. (e.g. to get an intrinsic bsize for flex
* items when resolving automatic minimum size in the main axis during flexbox
* layout.)
*/
UseAutoBSize,
/**
* Indicates that we should clamp the margin-box min-size to the given CB
* size. This is used for implementing the grid area clamping here:
* https://drafts.csswg.org/css-grid/#min-size-auto
*/
IClampMarginBoxMinSize, // clamp in our inline axis
BClampMarginBoxMinSize, // clamp in our block axis
/**
* The frame is stretching (per CSS Box Alignment) and doesn't have an
* Automatic Minimum Size in the indicated axis.
* (may be used for both flex/grid items, but currently only used for Grid)
* https://drafts.csswg.org/css-grid/#min-size-auto
* https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch
*/
IApplyAutoMinSize, // only has an effect when eShrinkWrap is false
};
using ComputeSizeFlags = mozilla::EnumSet<ComputeSizeFlag>;
/**
* The fallback size of width is 300px and the aspect-ratio is 2:1, based on
* CSS2 section 10.3.2 and CSS Sizing Level 3 section 5.1:
* https://drafts.csswg.org/css2/visudet.html#inline-replaced-width
* https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes
*/
inline constexpr CSSIntCoord kFallbackIntrinsicWidthInPixels(300);
inline constexpr CSSIntCoord kFallbackIntrinsicHeightInPixels(150);
inline constexpr CSSIntSize kFallbackIntrinsicSizeInPixels(
kFallbackIntrinsicWidthInPixels, kFallbackIntrinsicHeightInPixels);
inline constexpr nscoord kFallbackIntrinsicWidth =
kFallbackIntrinsicWidthInPixels * AppUnitsPerCSSPixel();
inline constexpr nscoord kFallbackIntrinsicHeight =
kFallbackIntrinsicHeightInPixels * AppUnitsPerCSSPixel();
inline constexpr nsSize kFallbackIntrinsicSize(kFallbackIntrinsicWidth,
kFallbackIntrinsicHeight);
/**
* This is used in some nsLayoutUtils functions.
* Declared here so that fewer files need to include nsLayoutUtils.h.
*/
enum class IntrinsicISizeType { MinISize, PrefISize };
} // namespace mozilla
#endif // LayoutConstants_h___

View File

@ -15,8 +15,8 @@
#include "nsViewportInfo.h"
#include "UnitTransforms.h"
#define MVM_LOG(...)
// #define MVM_LOG(...) printf_stderr("MVM: " __VA_ARGS__)
static mozilla::LazyLogModule sApzMvmLog("apz.mobileviewport");
#define MVM_LOG(...) MOZ_LOG(sApzMvmLog, LogLevel::Debug, (__VA_ARGS__))
NS_IMPL_ISUPPORTS(MobileViewportManager, nsIDOMEventListener, nsIObserver)
@ -34,7 +34,7 @@ MobileViewportManager::MobileViewportManager(MVMContext* aContext)
: mContext(aContext), mIsFirstPaint(false), mPainted(false) {
MOZ_ASSERT(mContext);
MVM_LOG("%p: creating with context %p\n", this, mContext);
MVM_LOG("%p: creating with context %p\n", this, mContext.get());
mContext->AddEventListener(DOM_META_ADDED, this, false);
mContext->AddEventListener(DOM_META_CHANGED, this, false);

View File

@ -26,7 +26,7 @@ RayReferenceData::RayReferenceData(const nsIFrame* aFrame) {
// for calculating the path length. We may need to update this.
// https://github.com/w3c/fxtf-drafts/issues/369
// FIXME: Bug 1579294: SVG layout may get a |container| with empty mRect
// (e.g. nsSVGOuterSVGAnonChildFrame), which makes the path length zero.
// (e.g. SVGOuterSVGAnonChildFrame), which makes the path length zero.
const nsIFrame* container = aFrame->GetContainingBlock();
if (!container) {
// If there is no parent frame, it's impossible to calculate the path

View File

@ -114,16 +114,16 @@ class OverflowChangedTracker {
frame->GetProperty(nsIFrame::DebugInitialOverflowPropertyApplied()),
"InitialOverflowProperty must be set first.");
nsOverflowAreas* overflow =
OverflowAreas* overflow =
frame->GetProperty(nsIFrame::InitialOverflowProperty());
if (overflow) {
// FinishAndStoreOverflow will change the overflow areas passed in,
// so make a copy.
nsOverflowAreas overflowCopy = *overflow;
OverflowAreas overflowCopy = *overflow;
frame->FinishAndStoreOverflow(overflowCopy, frame->GetSize());
} else {
nsRect bounds(nsPoint(0, 0), frame->GetSize());
nsOverflowAreas boundsOverflow;
OverflowAreas boundsOverflow;
boundsOverflow.SetAllTo(bounds);
frame->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
}

View File

@ -10,6 +10,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/MouseEventBinding.h"
#include "nsFrameList.h" // for DEBUG_FRAME_DUMP
#include "nsHTMLParts.h"
#include "nsLayoutUtils.h"
#include "nsGkAtoms.h"
@ -26,10 +27,11 @@
using namespace mozilla;
using namespace mozilla::dom;
// If debugging this code you may wish to enable this logging, and also
// uncomment the DumpFrameTree call near the bottom of the file.
#define PET_LOG(...)
// #define PET_LOG(...) printf_stderr("PET: " __VA_ARGS__);
// If debugging this code you may wish to enable this logging, via
// the env var MOZ_LOG="event.retarget:4". For extra logging (getting
// frame dumps, use MOZ_LOG="event.retarget:5".
static mozilla::LazyLogModule sEvtTgtLog("event.retarget");
#define PET_LOG(...) MOZ_LOG(sEvtTgtLog, LogLevel::Debug, (__VA_ARGS__))
namespace mozilla {
@ -246,12 +248,14 @@ static nsIContent* GetClickableAncestor(
return nullptr;
}
static nscoord AppUnitsFromMM(nsIFrame* aFrame, uint32_t aMM) {
nsPresContext* pc = aFrame->PresContext();
PresShell* presShell = pc->PresShell();
static nscoord AppUnitsFromMM(RelativeTo aFrame, uint32_t aMM) {
nsPresContext* pc = aFrame.mFrame->PresContext();
float result = float(aMM) * (pc->DeviceContext()->AppUnitsPerPhysicalInch() /
MM_PER_INCH_FLOAT);
result = result / presShell->GetResolution();
if (aFrame.mViewportType == ViewportType::Layout) {
PresShell* presShell = pc->PresShell();
result = result / presShell->GetResolution();
}
return NSToCoordRound(result);
}
@ -259,7 +263,7 @@ static nscoord AppUnitsFromMM(nsIFrame* aFrame, uint32_t aMM) {
* Clip aRect with the bounds of aFrame in the coordinate system of
* aRootFrame. aRootFrame is an ancestor of aFrame.
*/
static nsRect ClipToFrame(nsIFrame* aRootFrame, nsIFrame* aFrame,
static nsRect ClipToFrame(RelativeTo aRootFrame, const nsIFrame* aFrame,
nsRect& aRect) {
nsRect bound = nsLayoutUtils::TransformFrameRectToAncestor(
aFrame, nsRect(nsPoint(0, 0), aFrame->GetSize()), aRootFrame);
@ -267,9 +271,9 @@ static nsRect ClipToFrame(nsIFrame* aRootFrame, nsIFrame* aFrame,
return result;
}
static nsRect GetTargetRect(nsIFrame* aRootFrame,
static nsRect GetTargetRect(RelativeTo aRootFrame,
const nsPoint& aPointRelativeToRootFrame,
nsIFrame* aRestrictToDescendants,
const nsIFrame* aRestrictToDescendants,
const EventRadiusPrefs* aPrefs, uint32_t aFlags) {
nsMargin m(AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[0]),
AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[1]),
@ -325,23 +329,26 @@ static void SubtractFromExposedRegion(nsRegion* aExposedRegion,
}
}
static nsIFrame* GetClosest(
nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
const nsRect& aTargetRect, const EventRadiusPrefs* aPrefs,
nsIFrame* aRestrictToDescendants, nsIContent* aClickableAncestor,
nsTArray<nsIFrame*>& aCandidates) {
static nsIFrame* GetClosest(RelativeTo aRoot,
const nsPoint& aPointRelativeToRootFrame,
const nsRect& aTargetRect,
const EventRadiusPrefs* aPrefs,
const nsIFrame* aRestrictToDescendants,
nsIContent* aClickableAncestor,
nsTArray<nsIFrame*>& aCandidates) {
nsIFrame* bestTarget = nullptr;
// Lower is better; distance is in appunits
float bestDistance = 1e6f;
nsRegion exposedRegion(aTargetRect);
for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
nsIFrame* f = aCandidates[i];
PET_LOG("Checking candidate %p\n", f);
bool preservesAxisAlignedRectangles = false;
nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(
f, nsRect(nsPoint(0, 0), f->GetSize()), aRoot,
&preservesAxisAlignedRectangles);
PET_LOG("Checking candidate %p with border box %s\n", f,
mozilla::layers::Stringify(borderBox).c_str());
nsRegion region;
region.And(exposedRegion, borderBox);
if (region.IsEmpty()) {
@ -370,13 +377,13 @@ static nsIFrame* GetClosest(
}
// If our current closest frame is a descendant of 'f', skip 'f' (prefer
// the nested frame).
if (bestTarget &&
nsLayoutUtils::IsProperAncestorFrameCrossDoc(f, bestTarget, aRoot)) {
if (bestTarget && nsLayoutUtils::IsProperAncestorFrameCrossDoc(
f, bestTarget, aRoot.mFrame)) {
PET_LOG(" candidate %p was ancestor for bestTarget %p\n", f, bestTarget);
continue;
}
if (!aClickableAncestor && !nsLayoutUtils::IsAncestorFrameCrossDoc(
aRestrictToDescendants, f, aRoot)) {
aRestrictToDescendants, f, aRoot.mFrame)) {
PET_LOG(" candidate %p was not descendant of restrictroot %p\n", f,
aRestrictToDescendants);
continue;
@ -401,7 +408,7 @@ static nsIFrame* GetClosest(
}
nsIFrame* FindFrameTargetedByInputEvent(
WidgetGUIEvent* aEvent, nsIFrame* aRootFrame,
WidgetGUIEvent* aEvent, RelativeTo aRootFrame,
const nsPoint& aPointRelativeToRootFrame, uint32_t aFlags) {
using FrameForPointOption = nsLayoutUtils::FrameForPointOption;
EnumSet<FrameForPointOption> options;
@ -411,17 +418,14 @@ nsIFrame* FindFrameTargetedByInputEvent(
nsIFrame* target = nsLayoutUtils::GetFrameForPoint(
aRootFrame, aPointRelativeToRootFrame, options);
PET_LOG(
"Found initial target %p for event class %s point %s relative to root "
"frame %p\n",
target,
(aEvent->mClass == eMouseEventClass
? "mouse"
: (aEvent->mClass == eTouchEventClass ? "touch" : "other")),
"Found initial target %p for event class %s message %s point %s "
"relative to root frame %s\n",
target, ToChar(aEvent->mClass), ToChar(aEvent->mMessage),
mozilla::layers::Stringify(aPointRelativeToRootFrame).c_str(),
aRootFrame);
ToString(aRootFrame).c_str());
const EventRadiusPrefs* prefs = GetPrefsFor(aEvent->mClass);
if (!prefs || !prefs->mEnabled) {
if (!prefs || !prefs->mEnabled || EventRetargetSuppression::IsActive()) {
PET_LOG("Retargeting disabled\n");
return target;
}
@ -452,8 +456,8 @@ nsIFrame* FindFrameTargetedByInputEvent(
// a mouse event handler for example, targets that are !GetClickableAncestor
// can never be targeted --- something nsSubDocumentFrame in an ancestor
// document would be targeted instead.
nsIFrame* restrictToDescendants =
target ? target->PresShell()->GetRootFrame() : aRootFrame;
const nsIFrame* restrictToDescendants =
target ? target->PresShell()->GetRootFrame() : aRootFrame.mFrame;
nsRect targetRect = GetTargetRect(aRootFrame, aPointRelativeToRootFrame,
restrictToDescendants, prefs, aFlags);
@ -466,18 +470,22 @@ nsIFrame* FindFrameTargetedByInputEvent(
return target;
}
nsIFrame* closestClickable = GetClosest(
aRootFrame, aPointRelativeToRootFrame, targetRect, prefs,
restrictToDescendants, clickableAncestor, candidates);
nsIFrame* closestClickable =
GetClosest(aRootFrame, aPointRelativeToRootFrame, targetRect, prefs,
restrictToDescendants, clickableAncestor, candidates);
if (closestClickable) {
target = closestClickable;
}
PET_LOG("Final target is %p\n", target);
// Uncomment this to dump the frame tree to help with debugging.
#ifdef DEBUG_FRAME_DUMP
// At verbose logging level, dump the frame tree to help with debugging.
// Note that dumping the frame tree at the top of the function may flood
// logcat on Android devices and cause the PET_LOGs to get dropped.
// aRootFrame->DumpFrameTree();
if (MOZ_LOG_TEST(sEvtTgtLog, LogLevel::Verbose)) {
aRootFrame.mFrame->DumpFrameTree();
}
#endif
if (!target || !prefs->mRepositionEventCoords) {
// No repositioning required for this event
@ -488,22 +496,23 @@ nsIFrame* FindFrameTargetedByInputEvent(
// clamp it to the bounds, and then make it relative to the root frame again.
nsPoint point = aPointRelativeToRootFrame;
if (nsLayoutUtils::TRANSFORM_SUCCEEDED !=
nsLayoutUtils::TransformPoint(aRootFrame, target, point)) {
nsLayoutUtils::TransformPoint(aRootFrame, RelativeTo{target}, point)) {
return target;
}
point = target->GetRectRelativeToSelf().ClampPoint(point);
if (nsLayoutUtils::TRANSFORM_SUCCEEDED !=
nsLayoutUtils::TransformPoint(target, aRootFrame, point)) {
nsLayoutUtils::TransformPoint(RelativeTo{target}, aRootFrame, point)) {
return target;
}
// Now we basically undo the operations in GetEventCoordinatesRelativeTo, to
// get back the (now-clamped) coordinates in the event's widget's space.
nsView* view = aRootFrame->GetView();
nsView* view = aRootFrame.mFrame->GetView();
if (!view) {
return target;
}
LayoutDeviceIntPoint widgetPoint = nsLayoutUtils::TranslateViewToWidget(
aRootFrame->PresContext(), view, point, aEvent->mWidget);
aRootFrame.mFrame->PresContext(), view, point, aRootFrame.mViewportType,
aEvent->mWidget);
if (widgetPoint.x != NS_UNCONSTRAINEDSIZE) {
// If that succeeded, we update the point in the event
aEvent->mRefPoint = widgetPoint;
@ -511,4 +520,12 @@ nsIFrame* FindFrameTargetedByInputEvent(
return target;
}
uint32_t EventRetargetSuppression::sSuppressionCount = 0;
EventRetargetSuppression::EventRetargetSuppression() { sSuppressionCount++; }
EventRetargetSuppression::~EventRetargetSuppression() { sSuppressionCount--; }
bool EventRetargetSuppression::IsActive() { return sSuppressionCount > 0; }
} // namespace mozilla

View File

@ -7,6 +7,7 @@
#include <stdint.h>
#include "mozilla/EventForwards.h"
#include "RelativeTo.h"
class nsIFrame;
struct nsPoint;
@ -20,9 +21,19 @@ enum { INPUT_IGNORE_ROOT_SCROLL_FRAME = 0x01 };
* that are suitable targets, to account for inaccurate pointing devices.
*/
nsIFrame* FindFrameTargetedByInputEvent(
WidgetGUIEvent* aEvent, nsIFrame* aRootFrame,
WidgetGUIEvent* aEvent, RelativeTo aRootFrame,
const nsPoint& aPointRelativeToRootFrame, uint32_t aFlags = 0);
class MOZ_RAII EventRetargetSuppression {
public:
EventRetargetSuppression();
~EventRetargetSuppression();
static bool IsActive();
private:
static uint32_t sSuppressionCount;
};
} // namespace mozilla
#endif /* mozilla_PositionedEventTargeting_h */

View File

@ -6,11 +6,13 @@
#include "mozilla/PresShell.h"
#include "Units.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/ContentIterator.h"
#include "mozilla/DisplayPortUtils.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/EventStates.h"
@ -33,6 +35,7 @@
#include "mozilla/TouchEvents.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/ViewportUtils.h"
#include "MobileViewportManager.h"
#include <algorithm>
@ -116,9 +119,9 @@
#include "nsStyleSheetService.h"
#include "gfxUtils.h"
#include "mozilla/SMILAnimationController.h"
#include "SVGContentUtils.h"
#include "SVGObserverUtils.h"
#include "SVGFragmentIdentifier.h"
#include "mozilla/dom/SVGAnimationElement.h"
#include "mozilla/SVGObserverUtils.h"
#include "mozilla/SVGFragmentIdentifier.h"
#include "nsFrameSelection.h"
#include "mozilla/dom/Performance.h"
@ -230,6 +233,11 @@ struct RangePaintInfo {
// offset of builder's reference frame to the root frame
nsPoint mRootOffset;
// Resolution at which the items are normally painted. So if we're painting
// these items in a range separately from the "full display list", we may want
// to paint them at this resolution.
float mResolution = 1.0;
RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
: mRange(aRange),
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false) {
@ -2304,10 +2312,10 @@ PresShell::ScrollPage(bool aForward) {
nsIScrollableFrame* scrollFrame =
GetScrollableFrameToScroll(ScrollableDirection::Vertical);
if (scrollFrame) {
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::PAGES,
ScrollMode::Smooth, nullptr, nullptr,
nsIScrollableFrame::NOT_MOMENTUM,
nsIScrollableFrame::ENABLE_SNAP);
scrollFrame->ScrollBy(
nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::PAGES, ScrollMode::Smooth,
nullptr, mozilla::ScrollOrigin::NotSpecified,
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
}
return NS_OK;
}
@ -2320,10 +2328,10 @@ PresShell::ScrollLine(bool aForward) {
int32_t lineCount =
Preferences::GetInt("toolkit.scrollbox.verticalScrollDistance",
NS_DEFAULT_VERTICAL_SCROLL_DISTANCE);
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? lineCount : -lineCount),
ScrollUnit::LINES, ScrollMode::Smooth, nullptr,
nullptr, nsIScrollableFrame::NOT_MOMENTUM,
nsIScrollableFrame::ENABLE_SNAP);
scrollFrame->ScrollBy(
nsIntPoint(0, aForward ? lineCount : -lineCount), ScrollUnit::LINES,
ScrollMode::Smooth, nullptr, mozilla::ScrollOrigin::NotSpecified,
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
}
return NS_OK;
}
@ -2336,10 +2344,10 @@ PresShell::ScrollCharacter(bool aRight) {
int32_t h =
Preferences::GetInt("toolkit.scrollbox.horizontalScrollDistance",
NS_DEFAULT_HORIZONTAL_SCROLL_DISTANCE);
scrollFrame->ScrollBy(nsIntPoint(aRight ? h : -h, 0), ScrollUnit::LINES,
ScrollMode::Smooth, nullptr, nullptr,
nsIScrollableFrame::NOT_MOMENTUM,
nsIScrollableFrame::ENABLE_SNAP);
scrollFrame->ScrollBy(
nsIntPoint(aRight ? h : -h, 0), ScrollUnit::LINES, ScrollMode::Smooth,
nullptr, mozilla::ScrollOrigin::NotSpecified,
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
}
return NS_OK;
}
@ -2349,10 +2357,10 @@ PresShell::CompleteScroll(bool aForward) {
nsIScrollableFrame* scrollFrame =
GetScrollableFrameToScroll(ScrollableDirection::Vertical);
if (scrollFrame) {
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::WHOLE,
ScrollMode::Smooth, nullptr, nullptr,
nsIScrollableFrame::NOT_MOMENTUM,
nsIScrollableFrame::ENABLE_SNAP);
scrollFrame->ScrollBy(
nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::WHOLE, ScrollMode::Smooth,
nullptr, mozilla::ScrollOrigin::NotSpecified,
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
}
return NS_OK;
}
@ -2508,6 +2516,10 @@ void PresShell::EndLoad(Document* aDocument) {
mDocumentLoading = false;
}
bool PresShell::IsLayoutFlushObserver() {
return GetPresContext()->RefreshDriver()->IsLayoutFlushObserver(this);
}
void PresShell::LoadComplete() {
gfxTextPerfMetrics* tp = nullptr;
if (mPresContext) {
@ -2644,7 +2656,7 @@ void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
// Grab |wasDirty| now so we can go ahead and update the bits on
// subtreeRoot.
bool wasDirty = NS_SUBTREE_DIRTY(subtreeRoot);
bool wasDirty = subtreeRoot->IsSubtreeDirty();
subtreeRoot->AddStateBits(aBitToAdd);
// Determine whether we need to keep looking for the next ancestor
@ -2685,8 +2697,7 @@ void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
for (nsIFrame* a = subtreeRoot;
a && !CanStopClearingAncestorIntrinsics(a); a = a->GetParent()) {
a->MarkIntrinsicISizesDirty();
if (a->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
a->IsAbsolutelyPositioned()) {
if (a->IsAbsolutelyPositioned()) {
// If we get here, 'a' is abspos, so its subtree's intrinsic sizing
// has no effect on its ancestors' intrinsic sizing. So, don't loop
// upwards any further.
@ -2761,7 +2772,7 @@ void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
nsIFrame* child = f;
f = f->GetParent();
wasDirty = NS_SUBTREE_DIRTY(f);
wasDirty = f->IsSubtreeDirty();
f->ChildIsDirty(child);
NS_ASSERTION(f->HasAnyStateBits(NS_FRAME_HAS_DIRTY_CHILDREN),
"ChildIsDirty didn't do its job");
@ -2810,18 +2821,6 @@ already_AddRefed<nsIContent> PresShell::GetSelectedContentForScrolling() const {
return selectedContent.forget();
}
nsIScrollableFrame* PresShell::GetNearestScrollableFrame(
nsIFrame* aFrame, ScrollableDirection aDirection) {
if (aDirection == ScrollableDirection::Either) {
return nsLayoutUtils::GetNearestScrollableFrame(aFrame);
}
return nsLayoutUtils::GetNearestScrollableFrameForDirection(
aFrame, aDirection == ScrollableDirection::Vertical
? nsLayoutUtils::eVertical
: nsLayoutUtils::eHorizontal);
}
nsIScrollableFrame* PresShell::GetScrollableFrameToScrollForContent(
nsIContent* aContent, ScrollableDirection aDirection) {
nsIScrollableFrame* scrollFrame = nullptr;
@ -2832,7 +2831,8 @@ nsIScrollableFrame* PresShell::GetScrollableFrameToScrollForContent(
if (scrollFrame) {
startFrame = scrollFrame->GetScrolledFrame();
}
scrollFrame = GetNearestScrollableFrame(startFrame, aDirection);
scrollFrame = nsLayoutUtils::GetNearestScrollableFrameForDirection(
startFrame, aDirection);
}
}
if (!scrollFrame) {
@ -2840,8 +2840,8 @@ nsIScrollableFrame* PresShell::GetScrollableFrameToScrollForContent(
if (!scrollFrame || !scrollFrame->GetScrolledFrame()) {
return nullptr;
}
scrollFrame =
GetNearestScrollableFrame(scrollFrame->GetScrolledFrame(), aDirection);
scrollFrame = nsLayoutUtils::GetNearestScrollableFrameForDirection(
scrollFrame->GetScrolledFrame(), aDirection);
}
return scrollFrame;
}
@ -3089,10 +3089,10 @@ nsresult PresShell::GoToAnchor(const nsAString& aAnchorName, bool aScroll,
// Search for anchor in the HTML namespace with a matching name
if (!content && !mDocument->IsHTMLDocument()) {
NS_NAMED_LITERAL_STRING(nameSpace, "http://www.w3.org/1999/xhtml");
constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
// Get the list of anchor elements
nsCOMPtr<nsINodeList> list =
mDocument->GetElementsByTagNameNS(nameSpace, NS_LITERAL_STRING("a"));
mDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
// Loop through the anchors looking for the first one with the given name.
for (uint32_t i = 0; true; i++) {
nsIContent* node = list->Item(i);
@ -3174,12 +3174,13 @@ nsresult PresShell::GoToAnchor(const nsAString& aAnchorName, bool aScroll,
}
// If the target is an animation element, activate the animation
if (content->IsNodeOfType(nsINode::eANIMATION)) {
SVGContentUtils::ActivateByHyperlink(content.get());
nsCOMPtr<SVGAnimationElement> animationElement = do_QueryInterface(content);
if (animationElement) {
animationElement->ActivateByHyperlink();
}
} else {
rv = NS_ERROR_FAILURE;
NS_NAMED_LITERAL_STRING(top, "top");
constexpr auto top = u"top"_ns;
if (nsContentUtils::EqualsIgnoreASCIICase(aAnchorName, top)) {
// Scroll to the top/left if aAnchorName is "top" and there is no element
// with such a name or id.
@ -3267,19 +3268,12 @@ static void AccumulateFrameBounds(nsIFrame* aContainerFrame, nsIFrame* aFrame,
if (aLines) {
int32_t index = aLines->FindLineContaining(prevFrame, aCurLine);
if (index >= 0) {
aCurLine = index;
nsIFrame* trash1;
int32_t trash2;
nsRect lineBounds;
if (NS_SUCCEEDED(
aLines->GetLine(index, &trash1, &trash2, lineBounds))) {
frameBounds += frame->GetOffsetTo(f);
frame = f;
if (lineBounds.y < frameBounds.y) {
frameBounds.height = frameBounds.YMost() - lineBounds.y;
frameBounds.y = lineBounds.y;
}
auto line = aLines->GetLine(index).unwrap();
frameBounds += frame->GetOffsetTo(f);
frame = f;
if (line.mLineBounds.y < frameBounds.y) {
frameBounds.height = frameBounds.YMost() - line.mLineBounds.y;
frameBounds.y = line.mLineBounds.y;
}
}
}
@ -3624,7 +3618,8 @@ bool PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame, const nsRect& aRect,
}
nsIFrame* parent;
if (container->IsTransformed()) {
container->GetTransformMatrix(nullptr, &parent);
container->GetTransformMatrix(ViewportType::Layout, RelativeTo{nullptr},
&parent);
rect =
nsLayoutUtils::TransformFrameRectToAncestor(container, rect, parent);
} else {
@ -4716,8 +4711,8 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
// XXX deal with frame being null due to display:contents
for (; frame;
frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
info->mBuilder.SetVisibleRect(frame->GetVisualOverflowRect());
info->mBuilder.SetDirtyRect(frame->GetVisualOverflowRect());
info->mBuilder.SetVisibleRect(frame->InkOverflowRect());
info->mBuilder.SetDirtyRect(frame->InkOverflowRect());
frame->BuildDisplayListForStackingContext(&info->mBuilder, &info->mList);
}
};
@ -4733,6 +4728,32 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
BuildDisplayListForNode(endContainer);
}
// If one of the ancestor presShells (including this one) has a resolution
// set, we may have some APZ zoom applied. That means we may want to rasterize
// the nodes at that zoom level. Populate `info` with the relevant information
// so that the caller can decide what to do. Also wrap the display list in
// appropriate nsDisplayAsyncZoom display items. This code handles the general
// case with nested async zooms (even though that never actually happens),
// because it fell out of the implementation for free.
for (nsPresContext* ctx = GetPresContext(); ctx;
ctx = ctx->GetParentPresContext()) {
PresShell* shell = ctx->PresShell();
float resolution = shell->GetResolution();
if (resolution == 1.0) {
continue;
}
info->mResolution *= resolution;
nsIFrame* rootScrollFrame = shell->GetRootScrollFrame();
ViewID zoomedId =
nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent());
nsDisplayList wrapped;
wrapped.AppendNewToTop<nsDisplayAsyncZoom>(&info->mBuilder, rootScrollFrame,
&info->mList, nullptr, zoomedId);
info->mList.AppendToTop(&wrapped);
}
#ifdef DEBUG
if (gDumpRangePaintList) {
fprintf(stderr, "CreateRangePaintInfo --- before ClipListToRange:\n");
@ -4770,13 +4791,11 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
if (!pc || aArea.width == 0 || aArea.height == 0) return nullptr;
// use the rectangle to create the surface
nsIntRect pixelArea = aArea.ToOutsidePixels(pc->AppUnitsPerDevPixel());
LayoutDeviceIntRect pixelArea = LayoutDeviceIntRect::FromAppUnitsToOutside(
aArea, pc->AppUnitsPerDevPixel());
// if the image should not be resized, scale must be 1
float scale = 1.0;
nsIntRect rootScreenRect =
GetRootFrame()->GetScreenRectInAppUnits().ToNearestPixels(
pc->AppUnitsPerDevPixel());
nsRect maxSize;
pc->DeviceContext()->GetClientRect(maxSize);
@ -4788,8 +4807,8 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
// check if image-resizing-algorithm should be used
if (aFlags & RenderImageFlags::IsImage) {
// get max screensize
nscoord maxWidth = pc->AppUnitsToDevPixels(maxSize.width);
nscoord maxHeight = pc->AppUnitsToDevPixels(maxSize.height);
int32_t maxWidth = pc->AppUnitsToDevPixels(maxSize.width);
int32_t maxHeight = pc->AppUnitsToDevPixels(maxSize.height);
// resize image relative to the screensize
// get best height/width relative to screensize
float bestHeight = float(maxHeight) * RELATIVE_SCALEFACTOR;
@ -4808,8 +4827,8 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
scale = std::min(scale, adjustedScale);
} else {
// get half of max screensize
nscoord maxWidth = pc->AppUnitsToDevPixels(maxSize.width >> 1);
nscoord maxHeight = pc->AppUnitsToDevPixels(maxSize.height >> 1);
int32_t maxWidth = pc->AppUnitsToDevPixels(maxSize.width >> 1);
int32_t maxHeight = pc->AppUnitsToDevPixels(maxSize.height >> 1);
if (pixelArea.width > maxWidth || pixelArea.height > maxHeight) {
// divide the maximum size by the image size in both directions.
// Whichever direction produces the smallest result determines how much
@ -4821,19 +4840,65 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
}
}
// Pick a resolution scale factor that is the highest we need for any of
// the items. This means some items may get rendered at a higher-than-needed
// resolution but at least nothing will be avoidably blurry.
float resolutionScale = 1.0;
for (const UniquePtr<RangePaintInfo>& rangeInfo : aItems) {
resolutionScale = std::max(resolutionScale, rangeInfo->mResolution);
}
float unclampedResolution = resolutionScale;
// Clamp the resolution scale so that `pixelArea` when scaled by `scale` and
// `resolutionScale` isn't bigger than `maxSize`. This prevents creating
// giant/unbounded images.
resolutionScale =
std::min(resolutionScale, maxSize.width / (scale * pixelArea.width));
resolutionScale =
std::min(resolutionScale, maxSize.height / (scale * pixelArea.height));
// The following assert should only get hit if pixelArea scaled by `scale`
// alone would already have been bigger than `maxSize`, which should never
// be the case. For release builds we handle gracefully by reverting
// resolutionScale to 1.0 to avoid unexpected consequences.
MOZ_ASSERT(resolutionScale >= 1.0);
resolutionScale = std::max(1.0f, resolutionScale);
scale *= resolutionScale;
// Now we need adjust the output screen position of the surface based on the
// scaling factor and any APZ zoom that may be in effect. The goal is here
// to set `aScreenRect`'s top-left corner (in screen-relative LD pixels)
// such that the scaling effect on the surface appears anchored at `aPoint`
// ("anchor" here is like "transform-origin"). When this code is e.g. used
// to generate a drag image for dragging operations, `aPoint` refers to the
// position of the mouse cursor (also in screen-relative LD pixels), and the
// user-visible effect of doing this is that the point at which the user
// clicked to start the drag remains under the mouse during the drag.
// In order to do this we first compute the top-left corner of the
// pixelArea is screen-relative LD pixels.
LayoutDevicePoint visualPoint = ViewportUtils::ToScreenRelativeVisual(
LayoutDevicePoint(pixelArea.TopLeft()), pc);
// And then adjust the output screen position based on that, which we can do
// since everything here is screen-relative LD pixels. Note that the scale
// factor we use here is the effective "transform" scale applied to the
// content we're painting, relative to the scale at which it would normally
// get painted at as part of page rendering (`unclampedResolution`).
float scaleRelativeToNormalContent = scale / unclampedResolution;
aScreenRect->x = NSToIntFloor(aPoint.x - float(aPoint.x - visualPoint.x) *
scaleRelativeToNormalContent);
aScreenRect->y = NSToIntFloor(aPoint.y - float(aPoint.y - visualPoint.y) *
scaleRelativeToNormalContent);
pixelArea.width = NSToIntFloor(float(pixelArea.width) * scale);
pixelArea.height = NSToIntFloor(float(pixelArea.height) * scale);
if (!pixelArea.width || !pixelArea.height) return nullptr;
// adjust the screen position based on the rescaled size
nscoord left = rootScreenRect.x + pixelArea.x;
nscoord top = rootScreenRect.y + pixelArea.y;
aScreenRect->x = NSToIntFloor(aPoint.x - float(aPoint.x - left) * scale);
aScreenRect->y = NSToIntFloor(aPoint.y - float(aPoint.y - top) * scale);
if (!pixelArea.width || !pixelArea.height) {
return nullptr;
}
} else {
// move aScreenRect to the position of the surface in screen coordinates
aScreenRect->MoveTo(rootScreenRect.x + pixelArea.x,
rootScreenRect.y + pixelArea.y);
LayoutDevicePoint visualPoint = ViewportUtils::ToScreenRelativeVisual(
LayoutDevicePoint(pixelArea.TopLeft()), pc);
aScreenRect->MoveTo(RoundedToInt(visualPoint));
}
aScreenRect->width = pixelArea.width;
aScreenRect->height = pixelArea.height;
@ -4870,7 +4935,9 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
gfxMatrix initialTM = ctx->CurrentMatrixDouble();
if (resize) initialTM.PreScale(scale, scale);
if (resize) {
initialTM.PreScale(scale, scale);
}
// translate so that points are relative to the surface area
gfxPoint surfaceOffset = nsLayoutUtils::PointToGfxPoint(
@ -5239,7 +5306,7 @@ nsresult PresShell::SetResolutionAndScaleTo(float aResolution,
return NS_OK;
}
float PresShell::GetCumulativeResolution() {
float PresShell::GetCumulativeResolution() const {
float resolution = GetResolution();
nsPresContext* parentCtx = GetPresContext()->GetParentPresContext();
if (parentCtx) {
@ -5248,24 +5315,6 @@ float PresShell::GetCumulativeResolution() {
return resolution;
}
float PresShell::GetCumulativeNonRootScaleResolution() {
float resolution = 1.0;
PresShell* currentPresShell = this;
while (currentPresShell) {
nsPresContext* currentCtx = currentPresShell->GetPresContext();
if (currentCtx != currentCtx->GetRootPresContext()) {
resolution *= currentPresShell->GetResolution();
}
nsPresContext* parentCtx = currentCtx->GetParentPresContext();
if (parentCtx) {
currentPresShell = parentCtx->PresShell();
} else {
currentPresShell = nullptr;
}
}
return resolution;
}
void PresShell::SetRestoreResolution(float aResolution,
LayoutDeviceIntSize aDisplaySize) {
if (mMobileViewportManager) {
@ -5638,7 +5687,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
nsIScrollableFrame* scrollFrame = do_QueryFrame(aFrame);
if (scrollFrame) {
bool ignoreDisplayPort = false;
if (nsLayoutUtils::IsMissingDisplayPortBaseRect(aFrame->GetContent())) {
if (DisplayPortUtils::IsMissingDisplayPortBaseRect(aFrame->GetContent())) {
// We can properly set the base rect for root scroll frames on top level
// and root content documents. Otherwise the base rect we compute might
// be way too big without the limiting that
@ -5650,7 +5699,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
nsRect baseRect =
nsRect(nsPoint(0, 0),
nsLayoutUtils::CalculateCompositionSizeForFrame(aFrame));
nsLayoutUtils::SetDisplayPortBase(aFrame->GetContent(), baseRect);
DisplayPortUtils::SetDisplayPortBase(aFrame->GetContent(), baseRect);
} else {
ignoreDisplayPort = true;
}
@ -5659,8 +5708,8 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
nsRect displayPort;
bool usingDisplayport =
!ignoreDisplayPort &&
nsLayoutUtils::GetDisplayPortForVisibilityTesting(
aFrame->GetContent(), &displayPort, RelativeTo::ScrollFrame);
DisplayPortUtils::GetDisplayPortForVisibilityTesting(
aFrame->GetContent(), &displayPort);
scrollFrame->NotifyApproximateFrameVisibilityUpdate(!usingDisplayport);
@ -5684,7 +5733,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
for (nsIFrame* child : list) {
nsRect r = rect - child->GetPosition();
if (!r.IntersectRect(r, child->GetVisualOverflowRect())) {
if (!r.IntersectRect(r, child->InkOverflowRect())) {
continue;
}
if (child->IsTransformed()) {
@ -5692,7 +5741,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
// rect
if (!preserves3DChildren ||
!child->Combines3DTransformWithAncestors()) {
const nsRect overflow = child->GetVisualOverflowRectRelativeToSelf();
const nsRect overflow = child->InkOverflowRectRelativeToSelf();
nsRect out;
if (nsDisplayTransform::UntransformRect(r, overflow, child, &out)) {
r = out;
@ -5817,7 +5866,7 @@ bool PresShell::AssumeAllFramesVisible() {
if (!mHaveShutDown && !mIsDestroying &&
!mPresContext->IsRootContentDocument()) {
nsPresContext* presContext =
mPresContext->GetToplevelContentDocumentPresContext();
mPresContext->GetInProcessRootContentDocumentPresContext();
if (presContext && presContext->PresShell()->AssumeAllFramesVisible()) {
return true;
}
@ -5851,11 +5900,11 @@ void PresShell::ScheduleApproximateFrameVisibilityUpdateNow() {
if (!mPresContext->IsRootContentDocument()) {
nsPresContext* presContext =
mPresContext->GetToplevelContentDocumentPresContext();
mPresContext->GetInProcessRootContentDocumentPresContext();
if (!presContext) return;
MOZ_ASSERT(presContext->IsRootContentDocument(),
"Didn't get a root prescontext from "
"GetToplevelContentDocumentPresContext?");
"GetInProcessRootContentDocumentPresContext?");
presContext->PresShell()->ScheduleApproximateFrameVisibilityUpdateNow();
return;
}
@ -5950,7 +5999,7 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
if (contentRoot) {
uri = contentRoot->GetDocumentURI();
}
url = uri ? uri->GetSpecOrDefault() : NS_LITERAL_CSTRING("N/A");
url = uri ? uri->GetSpecOrDefault() : "N/A"_ns;
#ifdef MOZ_GECKO_PROFILER
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("PresShell::Paint", GRAPHICS, url);
#endif
@ -6360,8 +6409,8 @@ void PresShell::RecordMouseLocation(WidgetGUIEvent* aEvent) {
mPresContext, aEvent->mWidget, aEvent->mRefPoint, rootView);
mMouseEventTargetGuid = InputAPZContext::GetTargetLayerGuid();
} else {
mMouseLocation =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, rootFrame);
mMouseLocation = nsLayoutUtils::GetEventCoordinatesRelativeTo(
aEvent, RelativeTo{rootFrame, ViewportType::Visual});
mMouseEventTargetGuid = InputAPZContext::GetTargetLayerGuid();
}
#ifdef DEBUG_MOUSE_LOCATION
@ -6389,6 +6438,14 @@ void PresShell::RecordMouseLocation(WidgetGUIEvent* aEvent) {
}
}
void PresShell::nsSynthMouseMoveEvent::Revoke() {
if (mPresShell) {
mPresShell->GetPresContext()->RefreshDriver()->RemoveRefreshObserver(
this, FlushType::Display);
mPresShell = nullptr;
}
}
// static
nsIFrame* PresShell::EventHandler::GetNearestFrameContainingPresShell(
PresShell* aPresShell) {
@ -6701,7 +6758,7 @@ nsresult PresShell::EventHandler::HandleEventUsingCoordinates(
eventTargetData.mFrame->GetContent(), capturingContent))) {
// A check was already done above to ensure that capturingContent is
// in this presshell.
NS_ASSERTION(capturingContent->GetComposedDoc() == GetDocument(),
NS_ASSERTION(capturingContent->OwnerDoc() == GetDocument(),
"Unexpected document");
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
if (capturingFrame) {
@ -6791,13 +6848,41 @@ bool PresShell::EventHandler::MaybeFlushPendingNotifications(
}
}
// The type of coordinates to use for hit-testing input events
// that are relative to the RCD's viewport frame.
// On most platforms, use visual coordinates so that scrollbars
// can be targeted.
// On mobile, use layout coordinates because hit-testing in
// visual coordinates clashes with mobile viewport sizing, where
// the ViewportFrame is sized to the initial containing block
// (ICB) size, which is in layout coordinates. This is fine
// because we don't need to be able to target scrollbars on mobile
// (scrollbar dragging isn't supported).
static ViewportType ViewportTypeForInputEventsRelativeToRoot() {
#ifdef MOZ_WIDGET_ANDROID
return ViewportType::Layout;
#else
return ViewportType::Visual;
#endif
}
nsIFrame* PresShell::EventHandler::GetFrameToHandleNonTouchEvent(
nsIFrame* aRootFrameToHandleEvent, WidgetGUIEvent* aGUIEvent) {
MOZ_ASSERT(aGUIEvent);
MOZ_ASSERT(aGUIEvent->mClass != eTouchEventClass);
nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(
aGUIEvent, aRootFrameToHandleEvent);
ViewportType viewportType = ViewportType::Layout;
if (aRootFrameToHandleEvent->Type() == LayoutFrameType::Viewport) {
nsPresContext* pc = aRootFrameToHandleEvent->PresContext();
if (pc->IsChrome()) {
viewportType = ViewportType::Visual;
} else if (pc->IsRootContentDocument()) {
viewportType = ViewportTypeForInputEventsRelativeToRoot();
}
}
RelativeTo relativeTo{aRootFrameToHandleEvent, viewportType};
nsPoint eventPoint =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aGUIEvent, relativeTo);
uint32_t flags = 0;
if (aGUIEvent->mClass == eMouseEventClass) {
@ -6807,8 +6892,8 @@ nsIFrame* PresShell::EventHandler::GetFrameToHandleNonTouchEvent(
}
}
nsIFrame* targetFrame = FindFrameTargetedByInputEvent(
aGUIEvent, aRootFrameToHandleEvent, eventPoint, flags);
nsIFrame* targetFrame =
FindFrameTargetedByInputEvent(aGUIEvent, relativeTo, eventPoint, flags);
if (!targetFrame) {
return aRootFrameToHandleEvent;
}
@ -6837,8 +6922,8 @@ nsIFrame* PresShell::EventHandler::GetFrameToHandleNonTouchEvent(
}
// Finally, we need to recompute the target with the latest layout.
targetFrame = FindFrameTargetedByInputEvent(
aGUIEvent, aRootFrameToHandleEvent, eventPoint, flags);
targetFrame =
FindFrameTargetedByInputEvent(aGUIEvent, relativeTo, eventPoint, flags);
return targetFrame ? targetFrame : aRootFrameToHandleEvent;
}
@ -7294,8 +7379,7 @@ bool PresShell::EventHandler::MaybeDiscardOrDelayMouseEvent(
nsCOMPtr<EventTarget> eventTarget = aGUIEvent->mTarget;
RefPtr<Event> event = EventDispatcher::CreateEvent(
eventTarget, aFrameToHandleEvent->PresContext(), aGUIEvent,
EmptyString());
eventTarget, aFrameToHandleEvent->PresContext(), aGUIEvent, u""_ns);
suppressedListener->HandleEvent(*event);
return true;
@ -7450,7 +7534,7 @@ PresShell::EventHandler::ComputeRootFrameToHandleEventWithCapturingContent(
// A check was already done above to ensure that aCapturingContent is
// in this presshell.
NS_ASSERTION(aCapturingContent->GetComposedDoc() == GetDocument(),
NS_ASSERTION(aCapturingContent->OwnerDoc() == GetDocument(),
"Unexpected document");
nsIFrame* captureFrame = aCapturingContent->GetPrimaryFrame();
if (!captureFrame) {
@ -8568,6 +8652,12 @@ bool PresShell::EventHandler::AdjustContextMenuKeyEvent(
if (PrepareToUseCaretPosition(MOZ_KnownLive(aMouseEvent->mWidget),
caretPoint)) {
// caret position is good
int32_t devPixelRatio = GetPresContext()->AppUnitsPerDevPixel();
caretPoint = LayoutDeviceIntPoint::FromAppUnitsToNearest(
ViewportUtils::LayoutToVisual(
LayoutDeviceIntPoint::ToAppUnits(caretPoint, devPixelRatio),
GetPresContext()->PresShell()),
devPixelRatio);
aMouseEvent->mRefPoint = caretPoint;
return true;
}
@ -9172,8 +9262,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
#ifdef MOZ_GECKO_PROFILER
nsIURI* uri = mDocument->GetDocumentURI();
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(
"Reflow", LAYOUT_Reflow,
uri ? uri->GetSpecOrDefault() : NS_LITERAL_CSTRING("N/A"));
"Reflow", LAYOUT_Reflow, uri ? uri->GetSpecOrDefault() : "N/A"_ns);
#endif
gfxTextPerfMetrics* tp = mPresContext->GetTextPerfMetrics();
@ -9239,7 +9328,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
size = target->GetLogicalSize();
}
nsOverflowAreas oldOverflow; // initialized and used only when !isRoot
OverflowAreas oldOverflow; // initialized and used only when !isRoot
if (!isRoot) {
oldOverflow = target->GetOverflowAreas();
}
@ -9251,7 +9340,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
// constrained height implies page/column breaking.
LogicalSize reflowSize(wm, size.ISize(wm), NS_UNCONSTRAINEDSIZE);
ReflowInput reflowInput(mPresContext, target, rcx, reflowSize,
ReflowInput::CALLER_WILL_INIT);
ReflowInput::InitFlag::CallerWillInit);
reflowInput.mOrthogonalLimit = size.BSize(wm);
if (isRoot) {
@ -9275,9 +9364,9 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
// Initialize reflow input with current used border and padding,
// in case this was set specially by the parent frame when the reflow root
// was reflowed by its parent.
nsMargin currentBorder = target->GetUsedBorder();
nsMargin currentPadding = target->GetUsedPadding();
reflowInput.Init(mPresContext, Nothing(), &currentBorder, &currentPadding);
reflowInput.Init(mPresContext, Nothing(),
Some(target->GetLogicalUsedBorder(wm)),
Some(target->GetLogicalUsedPadding(wm)));
}
// fix the computed height
@ -9286,14 +9375,15 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
if (size.BSize(wm) != NS_UNCONSTRAINEDSIZE) {
nscoord computedBSize =
size.BSize(wm) -
reflowInput.ComputedLogicalBorderPadding().BStartEnd(wm);
reflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(wm);
computedBSize = std::max(computedBSize, 0);
reflowInput.SetComputedBSize(computedBSize);
}
NS_ASSERTION(reflowInput.ComputedISize() ==
size.ISize(wm) -
reflowInput.ComputedLogicalBorderPadding().IStartEnd(wm),
"reflow input computed incorrect inline size");
NS_ASSERTION(
reflowInput.ComputedISize() ==
size.ISize(wm) -
reflowInput.ComputedLogicalBorderPadding(wm).IStartEnd(wm),
"reflow input computed incorrect inline size");
mPresContext->ReflowStarted(aInterruptible);
mIsReflowing = true;
@ -9318,7 +9408,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
target->SetSize(boundsRelativeToTarget.Size());
// Always use boundsRelativeToTarget here, not
// desiredSize.GetVisualOverflowArea(), because for root frames (where they
// desiredSize.InkOverflowRect(), because for root frames (where they
// could be different, since root frames are allowed to have overflow) the
// root view bounds need to match the viewport bounds; the view manager
// "window dimensions" code depends on it.
@ -9358,7 +9448,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
for (auto iter = mFramesToDirty.Iter(); !iter.Done(); iter.Next()) {
// Mark frames dirty until target frame.
nsPtrHashKey<nsIFrame>* p = iter.Get();
for (nsIFrame* f = p->GetKey(); f && !NS_SUBTREE_DIRTY(f);
for (nsIFrame* f = p->GetKey(); f && !f->IsSubtreeDirty();
f = f->GetParent()) {
f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
if (f->IsFlexItem()) {
@ -9371,11 +9461,11 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
}
}
NS_ASSERTION(NS_SUBTREE_DIRTY(target), "Why is the target not dirty?");
NS_ASSERTION(target->IsSubtreeDirty(), "Why is the target not dirty?");
mDirtyRoots.Add(target);
SetNeedLayoutFlush();
// Clear mFramesToDirty after we've done the NS_SUBTREE_DIRTY(target)
// Clear mFramesToDirty after we've done the target->IsSubtreeDirty()
// assertion so that if it fails it's easier to see what's going on.
#ifdef NOISY_INTERRUPTIBLE_REFLOW
printf("mFramesToDirty.Count() == %u\n", mFramesToDirty.Count());
@ -9466,7 +9556,7 @@ bool PresShell::ProcessReflowCommands(bool aInterruptible) {
// Send an incremental reflow notification to the target frame.
nsIFrame* target = mDirtyRoots.PopShallowestRoot();
if (!NS_SUBTREE_DIRTY(target)) {
if (!target->IsSubtreeDirty()) {
// It's not dirty anymore, which probably means the notification
// was posted in the middle of a reflow (perhaps with a reflow
// root in the middle). Don't do anything.
@ -10036,13 +10126,20 @@ void PresShell::ListComputedStyles(FILE* out, int32_t aIndent) {
}
}
}
#endif
#if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
void PresShell::ListStyleSheets(FILE* out, int32_t aIndent) {
int32_t sheetCount = StyleSet()->SheetCount(StyleOrigin::Author);
for (int32_t i = 0; i < sheetCount; ++i) {
StyleSet()->SheetAt(StyleOrigin::Author, i)->List(out, aIndent);
fputs("\n", out);
}
auto ListStyleSheetsAtOrigin = [this, out, aIndent](StyleOrigin origin) {
int32_t sheetCount = StyleSet()->SheetCount(origin);
for (int32_t i = 0; i < sheetCount; ++i) {
StyleSet()->SheetAt(origin, i)->List(out, aIndent);
}
};
ListStyleSheetsAtOrigin(StyleOrigin::UserAgent);
ListStyleSheetsAtOrigin(StyleOrigin::User);
ListStyleSheetsAtOrigin(StyleOrigin::Author);
}
#endif
@ -10768,21 +10865,39 @@ void PresShell::ResetVisualViewportSize() {
bool PresShell::SetVisualViewportOffset(const nsPoint& aScrollOffset,
const nsPoint& aPrevLayoutScrollPos) {
nsPoint newOffset = aScrollOffset;
nsIScrollableFrame* rootScrollFrame = GetRootScrollFrameAsScrollable();
if (rootScrollFrame) {
// See the comment in nsHTMLScrollFrame::Reflow above the call to
// SetVisualViewportOffset for why we need to do this.
nsRect scrollRange = rootScrollFrame->GetScrollRangeForUserInputEvents();
if (!scrollRange.Contains(newOffset)) {
newOffset.x = std::min(newOffset.x, scrollRange.XMost());
newOffset.x = std::max(newOffset.x, scrollRange.x);
newOffset.y = std::min(newOffset.y, scrollRange.YMost());
newOffset.y = std::max(newOffset.y, scrollRange.y);
}
}
nsPoint prevOffset = GetVisualViewportOffset();
if (prevOffset == aScrollOffset) {
if (prevOffset == newOffset) {
return false;
}
mVisualViewportOffset = Some(aScrollOffset);
mVisualViewportOffset = Some(newOffset);
if (auto* window = nsGlobalWindowInner::Cast(mDocument->GetInnerWindow())) {
window->VisualViewport()->PostScrollEvent(prevOffset, aPrevLayoutScrollPos);
}
if (IsVisualViewportSizeSet()) {
if (IsVisualViewportSizeSet() && rootScrollFrame) {
rootScrollFrame->Anchor()->UserScrolled();
}
if (gfxPlatform::UseDesktopZoomingScrollbars()) {
if (nsIScrollableFrame* rootScrollFrame =
GetRootScrollFrameAsScrollable()) {
rootScrollFrame->Anchor()->UserScrolled();
rootScrollFrame->UpdateScrollbarPosition();
}
}
@ -11048,14 +11163,15 @@ nsIContent* PresShell::EventHandler::GetOverrideClickTarget(
WidgetMouseEvent* mouseEvent = aGUIEvent->AsMouseEvent();
uint32_t flags = 0;
RelativeTo relativeTo{aFrame};
nsPoint eventPoint =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aGUIEvent, aFrame);
nsLayoutUtils::GetEventCoordinatesRelativeTo(aGUIEvent, relativeTo);
if (mouseEvent->mIgnoreRootScrollFrame) {
flags |= INPUT_IGNORE_ROOT_SCROLL_FRAME;
}
nsIFrame* target =
FindFrameTargetedByInputEvent(aGUIEvent, aFrame, eventPoint, flags);
FindFrameTargetedByInputEvent(aGUIEvent, relativeTo, eventPoint, flags);
if (!target) {
return nullptr;
}
@ -11279,3 +11395,7 @@ void PresShell::EndPaint() {
});
}
}
bool PresShell::GetZoomableByAPZ() const {
return mZoomConstraintsClient && mZoomConstraintsClient->GetAllowZoom();
}

View File

@ -37,7 +37,7 @@
#include "nsPresArena.h"
#include "nsPresContext.h"
#include "nsRect.h"
#include "nsRefreshDriver.h"
#include "nsRefreshObservers.h"
#include "nsStringFwd.h"
#include "nsStubDocumentObserver.h"
#include "nsTHashtable.h"
@ -70,6 +70,7 @@ class nsITimer;
class nsPIDOMWindowOuter;
class nsPresShellEventCB;
class nsRange;
class nsRefreshDriver;
class nsRegion;
class nsView;
class nsViewManager;
@ -83,6 +84,8 @@ class ZoomConstraintsClient;
struct nsCallbackEventRequest;
enum class ScrollableDirection;
namespace mozilla {
class AccessibleCaretEventHub;
class EventStates;
@ -369,9 +372,7 @@ class PresShell final : public nsStubDocumentObserver,
/**
* Return true if the presshell expects layout flush.
*/
bool IsLayoutFlushObserver() {
return GetPresContext()->RefreshDriver()->IsLayoutFlushObserver(this);
}
bool IsLayoutFlushObserver();
/**
* Called when document load completes.
@ -423,15 +424,6 @@ class PresShell final : public nsStubDocumentObserver,
nsIScrollableFrame* GetScrollableFrameToScroll(
ScrollableDirection aDirection);
/**
* Gets nearest ancestor scrollable frame from aFrame. The frame is
* scrollable with overflow:scroll or overflow:auto in some direction when
* aDirection is eEither. Otherwise, this returns a nearest frame that is
* scrollable in the specified direction.
*/
nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame,
ScrollableDirection aDirection);
/**
* Returns the page sequence frame associated with the frame hierarchy.
* Returns nullptr if not a paginated view.
@ -544,7 +536,8 @@ class PresShell final : public nsStubDocumentObserver,
* Scrolls the view of the document so that the given area of a frame
* is visible, if possible. Layout is not flushed before scrolling.
*
* @param aRect relative to aFrame
* @param aRect Relative to aFrame. The rect edges will be respected even if
* the rect is empty.
* @param aVertical see ScrollContentIntoView and ScrollAxis
* @param aHorizontal see ScrollContentIntoView and ScrollAxis
* @param aScrollFlags if SCROLL_FIRST_ANCESTOR_ONLY is set, only the
@ -717,12 +710,13 @@ class PresShell final : public nsStubDocumentObserver,
bool IsPaintingFrameCounts();
#endif // #ifdef MOZ_REFLOW_PERF
#ifdef DEBUG
// Debugging hooks
#ifdef DEBUG
void ListComputedStyles(FILE* out, int32_t aIndent = 0);
#endif
#if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
void ListStyleSheets(FILE* out, int32_t aIndent = 0);
#endif // #ifdef DEBUG
#endif
/**
* Stop all active elements (plugins and the caret) in this presentation and
@ -931,7 +925,7 @@ class PresShell final : public nsStubDocumentObserver,
}
float GetResolution() const { return mResolution.valueOr(1.0); }
float GetCumulativeResolution();
float GetCumulativeResolution() const;
/**
* Accessors for a flag that tracks whether the most recent change to
@ -945,12 +939,6 @@ class PresShell final : public nsStubDocumentObserver,
*/
bool IsResolutionUpdatedByApz() const { return mResolutionUpdatedByApz; }
/**
* Calculate the cumulative scale resolution from this document up to
* but not including the root document.
*/
float GetCumulativeNonRootScaleResolution();
/**
* Used by session restore code to restore a resolution before the first
* paint.
@ -1664,6 +1652,8 @@ class PresShell final : public nsStubDocumentObserver,
nsIFrame* GetDrawEventTargetFrame() { return mDrawEventTargetFrame; }
#endif
bool GetZoomableByAPZ() const;
private:
~PresShell();
@ -1894,13 +1884,8 @@ class PresShell final : public nsStubDocumentObserver,
public:
NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent, override)
void Revoke() {
if (mPresShell) {
mPresShell->GetPresContext()->RefreshDriver()->RemoveRefreshObserver(
this, FlushType::Display);
mPresShell = nullptr;
}
}
void Revoke();
MOZ_CAN_RUN_SCRIPT
void WillRefresh(TimeStamp aTime) override {
if (mPresShell) {
@ -2906,10 +2891,10 @@ class PresShell final : public nsStubDocumentObserver,
// the mouse pointer may have changed without the mouse moving (eg scrolling,
// change to the document contents).
// It is set only on a presshell for a root document, this value represents
// the last observed location of the mouse relative to that root document. It
// is set to (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if the mouse isn't
// over our window or there is no last observed mouse location for some
// reason.
// the last observed location of the mouse relative to that root document,
// in visual coordinates. It is set to (NS_UNCONSTRAINEDSIZE,
// NS_UNCONSTRAINEDSIZE) if the mouse isn't over our window or there is no
// last observed mouse location for some reason.
nsPoint mMouseLocation;
// This is an APZ state variable that tracks the target guid for the last
// mouse event that was processed (corresponding to mMouseLocation). This is

View File

@ -146,8 +146,6 @@ enum class ScrollFlags {
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ScrollFlags)
enum class ScrollableDirection { Horizontal, Vertical, Either };
// See comment at declaration of RenderDocument() for the detail.
enum class RenderDocumentFlags {
None = 0,

49
layout/base/RelativeTo.h Normal file
View File

@ -0,0 +1,49 @@
/* 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/. */
#ifndef mozilla_RelativeTo_h
#define mozilla_RelativeTo_h
#include <ostream>
class nsIFrame;
namespace mozilla {
// A flag that can be used to annotate a frame to distinguish coordinates
// relative to the viewport frame as being in layout or visual coordinates.
enum class ViewportType { Layout, Visual };
// A struct that combines a frame with a ViewportType annotation. The
// combination completely describes what a set of coordinates is "relative to".
// Notes on expected usage:
// - The boundary between visual and layout coordinates is approximately
// at the root content document (RCD)'s ViewportFrame, which we'll
// call "RCD-VF".
// - Coordinates relative to the RCD-VF's descendants (other than the
// RCD's viewport scrollbar frames) should be in layout coordinates.
// - Coordinates relative to the RCD-VF's ancestors should be in visual
// coordinates (note that in an e10s setup, the RCD-VF doesn't
// typically have in-process ancestors).
// - Coordinates relative to the RCD-VF itself can be in either layout
// or visual coordinates.
struct RelativeTo {
const nsIFrame* mFrame = nullptr;
// Choose ViewportType::Layout as the default as this is what the vast
// majority of layout code deals with.
ViewportType mViewportType = ViewportType::Layout;
bool operator==(const RelativeTo& aOther) const {
return mFrame == aOther.mFrame && mViewportType == aOther.mViewportType;
}
friend std::ostream& operator<<(std::ostream& aOs, const RelativeTo& aR) {
return aOs << "{" << aR.mFrame << ", "
<< (aR.mViewportType == ViewportType::Visual ? "visual"
: "layout")
<< "}";
}
};
} // namespace mozilla
#endif // mozilla_RelativeTo_h

View File

@ -9,6 +9,7 @@
#include "mozilla/ComputedStyle.h"
#include "mozilla/ComputedStyleInlines.h"
#include "mozilla/DocumentStyleRootIterator.h"
#include "mozilla/EffectSet.h"
#include "mozilla/GeckoBindings.h"
#include "mozilla/LayerAnimationInfo.h"
#include "mozilla/layers/AnimationInfo.h"
@ -18,8 +19,13 @@
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleSetInlines.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/SVGIntegrationUtils.h"
#include "mozilla/SVGObserverUtils.h"
#include "mozilla/SVGTextFrame.h"
#include "mozilla/SVGUtils.h"
#include "mozilla/Unused.h"
#include "mozilla/ViewportFrame.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/dom/ChildIterator.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/ElementInlines.h"
@ -43,12 +49,7 @@
#include "nsStyleUtil.h"
#include "nsTransitionManager.h"
#include "StickyScrollContainer.h"
#include "mozilla/EffectSet.h"
#include "mozilla/IntegerRange.h"
#include "SVGObserverUtils.h"
#include "SVGTextFrame.h"
#include "ActiveLayerTracker.h"
#include "nsSVGIntegrationUtils.h"
#ifdef ACCESSIBILITY
# include "nsAccessibilityService.h"
@ -465,11 +466,8 @@ static bool StateChangeMayAffectFrame(const Element& aElement,
return false;
}
const bool brokenChanged = aStates.HasAtLeastOneOfStates(
NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED |
NS_EVENT_STATE_SUPPRESSED);
const bool loadingChanged =
aStates.HasAtLeastOneOfStates(NS_EVENT_STATE_LOADING);
const bool brokenChanged = aStates.HasState(NS_EVENT_STATE_BROKEN);
const bool loadingChanged = aStates.HasState(NS_EVENT_STATE_LOADING);
if (!brokenChanged && !loadingChanged) {
return false;
@ -653,7 +651,7 @@ static nsIFrame* GetFrameForChildrenOnlyTransformHint(nsIFrame* aFrame) {
if (aFrame->IsSVGOuterSVGFrame()) {
aFrame = aFrame->PrincipalChildList().FirstChild();
MOZ_ASSERT(aFrame->IsSVGOuterSVGAnonChildFrame(),
"Where is the nsSVGOuterSVGFrame's anon child??");
"Where is the SVGOuterSVGFrame's anon child??");
}
MOZ_ASSERT(aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer),
"Children-only transforms only expected on SVG frames");
@ -693,9 +691,23 @@ static bool RecomputePosition(nsIFrame* aFrame) {
return false;
}
// Flexbox and Grid layout supports CSS Align and the optimizations below
// don't support that yet.
if (aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
// If the frame has an intrinsic block-size, we resolve its 'auto' margins
// after doing layout, since we need to know the frame's block size. See
// nsAbsoluteContainingBlock::ResolveAutoMarginsAfterLayout().
//
// Since the size of the frame doesn't change, we could modify the below
// computation to compute the margin correctly without doing a full reflow,
// however we decided to try doing a full reflow for now.
if (aFrame->HasIntrinsicKeywordForBSize()) {
WritingMode wm = aFrame->GetWritingMode();
const auto* styleMargin = aFrame->StyleMargin();
if (styleMargin->HasBlockAxisAuto(wm)) {
return false;
}
}
// Flexbox and Grid layout supports CSS Align and the optimizations below
// don't support that yet.
nsIFrame* ph = aFrame->GetPlaceholderFrame();
if (ph && ph->HasAnyStateBits(PLACEHOLDER_STATICPOS_NEEDS_CSSALIGN)) {
return false;
@ -744,14 +756,11 @@ static bool RecomputePosition(nsIFrame* aFrame) {
for (nsIFrame* cont = aFrame; cont;
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
nsIFrame* cb = cont->GetContainingBlock();
nsMargin newOffsets;
WritingMode wm = cb->GetWritingMode();
const LogicalSize size = cb->ContentSize();
ReflowInput::ComputeRelativeOffsets(wm, cont, size, newOffsets);
NS_ASSERTION(newOffsets.left == -newOffsets.right &&
newOffsets.top == -newOffsets.bottom,
"ComputeRelativeOffsets should return valid results");
const LogicalSize cbSize = cb->ContentSize();
const LogicalMargin newLogicalOffsets =
ReflowInput::ComputeRelativeOffsets(wm, cont, cbSize);
const nsMargin newOffsets = newLogicalOffsets.GetPhysicalMargin(wm);
// ReflowInput::ApplyRelativePositioning would work here, but
// since we've already checked mPosition and aren't changing the frame's
@ -803,12 +812,15 @@ static bool RecomputePosition(nsIFrame* aFrame) {
nsIFrame* cbFrame = parentFrame->GetContainingBlock();
if (cbFrame && (aFrame->GetContainingBlock() != parentFrame ||
parentFrame->IsTableFrame())) {
const auto cbWM = cbFrame->GetWritingMode();
LogicalSize cbSize = cbFrame->GetLogicalSize();
cbReflowInput.emplace(cbFrame->PresContext(), cbFrame, rc, cbSize);
cbReflowInput->ComputedPhysicalMargin() = cbFrame->GetUsedMargin();
cbReflowInput->ComputedPhysicalPadding() = cbFrame->GetUsedPadding();
cbReflowInput->ComputedPhysicalBorderPadding() =
cbFrame->GetUsedBorderAndPadding();
cbReflowInput->SetComputedLogicalMargin(
cbWM, cbFrame->GetLogicalUsedMargin(cbWM));
cbReflowInput->SetComputedLogicalPadding(
cbWM, cbFrame->GetLogicalUsedPadding(cbWM));
cbReflowInput->SetComputedLogicalBorderPadding(
cbWM, cbFrame->GetLogicalUsedBorderAndPadding(cbWM));
parentReflowInput.mCBReflowInput = cbReflowInput.ptr();
}
@ -817,11 +829,12 @@ static bool RecomputePosition(nsIFrame* aFrame) {
"parentSize should be valid");
parentReflowInput.SetComputedISize(std::max(parentSize.ISize(parentWM), 0));
parentReflowInput.SetComputedBSize(std::max(parentSize.BSize(parentWM), 0));
parentReflowInput.ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
parentReflowInput.SetComputedLogicalMargin(parentWM, LogicalMargin(parentWM));
parentReflowInput.ComputedPhysicalPadding() = parentFrame->GetUsedPadding();
parentReflowInput.ComputedPhysicalBorderPadding() =
parentFrame->GetUsedBorderAndPadding();
parentReflowInput.SetComputedLogicalPadding(
parentWM, parentFrame->GetLogicalUsedPadding(parentWM));
parentReflowInput.SetComputedLogicalBorderPadding(
parentWM, parentFrame->GetLogicalUsedBorderAndPadding(parentWM));
LogicalSize availSize = parentSize.ConvertTo(frameWM, parentWM);
availSize.BSize(frameWM) = NS_UNCONSTRAINEDSIZE;
@ -839,11 +852,10 @@ static bool RecomputePosition(nsIFrame* aFrame) {
availSize, Some(lcbSize));
nscoord computedISize = reflowInput.ComputedISize();
nscoord computedBSize = reflowInput.ComputedBSize();
computedISize +=
reflowInput.ComputedLogicalBorderPadding().IStartEnd(frameWM);
const auto frameBP = reflowInput.ComputedLogicalBorderPadding(frameWM);
computedISize += frameBP.IStartEnd(frameWM);
if (computedBSize != NS_UNCONSTRAINEDSIZE) {
computedBSize +=
reflowInput.ComputedLogicalBorderPadding().BStartEnd(frameWM);
computedBSize += frameBP.BStartEnd(frameWM);
}
LogicalSize logicalSize = aFrame->GetLogicalSize(frameWM);
nsSize size = aFrame->GetSize();
@ -860,26 +872,26 @@ static bool RecomputePosition(nsIFrame* aFrame) {
// match the reflow code path.
//
// TODO(emilio): It'd be nice if this did logical math instead, but it seems
// to me the math should work out on vertical writing modes as well.
if (NS_AUTOOFFSET == reflowInput.ComputedPhysicalOffsets().left) {
reflowInput.ComputedPhysicalOffsets().left =
cbSize.width - reflowInput.ComputedPhysicalOffsets().right -
reflowInput.ComputedPhysicalMargin().right - size.width -
reflowInput.ComputedPhysicalMargin().left;
// to me the math should work out on vertical writing modes as well. See Bug
// 1675861 for some hints.
const nsMargin offset = reflowInput.ComputedPhysicalOffsets();
const nsMargin margin = reflowInput.ComputedPhysicalMargin();
nscoord left = offset.left;
if (left == NS_AUTOOFFSET) {
left =
cbSize.width - offset.right - margin.right - size.width - margin.left;
}
if (NS_AUTOOFFSET == reflowInput.ComputedPhysicalOffsets().top) {
reflowInput.ComputedPhysicalOffsets().top =
cbSize.height - reflowInput.ComputedPhysicalOffsets().bottom -
reflowInput.ComputedPhysicalMargin().bottom - size.height -
reflowInput.ComputedPhysicalMargin().top;
nscoord top = offset.top;
if (top == NS_AUTOOFFSET) {
top = cbSize.height - offset.bottom - margin.bottom - size.height -
margin.top;
}
// Move the frame
nsPoint pos(parentBorder.left + reflowInput.ComputedPhysicalOffsets().left +
reflowInput.ComputedPhysicalMargin().left,
parentBorder.top + reflowInput.ComputedPhysicalOffsets().top +
reflowInput.ComputedPhysicalMargin().top);
nsPoint pos(parentBorder.left + left + margin.left,
parentBorder.top + top + margin.top);
aFrame->SetPosition(pos);
if (aFrame->IsInScrollAnchorChain()) {
@ -928,7 +940,7 @@ static bool ContainingBlockChangeAffectsDescendants(
nsIFrame* outOfFlow = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
// If SVG text frames could appear here, they could confuse us since
// they ignore their position style ... but they can't.
NS_ASSERTION(!nsSVGUtils::IsInSVGTextSubtree(outOfFlow),
NS_ASSERTION(!SVGUtils::IsInSVGTextSubtree(outOfFlow),
"SVG text frames can't be out of flow");
auto* display = outOfFlow->StyleDisplay();
if (display->IsAbsolutelyPositionedStyle()) {
@ -1028,7 +1040,7 @@ static void DoApplyRenderingChangeToTree(nsIFrame* aFrame,
aFrame->IsFrameOfType(nsIFrame::eSVG) &&
!aFrame->IsSVGOuterSVGFrame()) {
// Need to update our overflow rects:
nsSVGUtils::ScheduleReflowSVG(aFrame);
SVGUtils::ScheduleReflowSVG(aFrame);
}
ActiveLayerTracker::NotifyNeedsRepaint(aFrame);
@ -1039,7 +1051,7 @@ static void DoApplyRenderingChangeToTree(nsIFrame* aFrame,
needInvalidatingPaint = true;
ActiveLayerTracker::NotifyRestyle(aFrame, eCSSProperty_opacity);
if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
if (SVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
// SVG effects paints the opacity without using
// nsDisplayOpacity. We need to invalidate manually.
aFrame->InvalidateFrameSubtree();
@ -1559,9 +1571,9 @@ void RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList) {
// opacity layer change hint when we do opacity optimization for SVG.
// We can't do it in nsStyleEffects::CalcDifference() just like we do
// for the optimization for 0.99 over opacity values since we have no way
// to call nsSVGUtils::CanOptimizeOpacity() there.
// to call SVGUtils::CanOptimizeOpacity() there.
if ((hint & nsChangeHint_UpdateOpacityLayer) &&
nsSVGUtils::CanOptimizeOpacity(frame)) {
SVGUtils::CanOptimizeOpacity(frame)) {
hint &= ~nsChangeHint_UpdateOpacityLayer;
hint |= nsChangeHint_RepaintFrame;
}

View File

@ -9,7 +9,7 @@
#include "nsCSSRendering.h"
#include "nsMargin.h"
#include "nsStyleStruct.h"
#include "SVGContentUtils.h"
#include "mozilla/SVGContentUtils.h"
namespace mozilla {

View File

@ -0,0 +1,100 @@
/* 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/. */
#ifndef mozilla_SurfaceFromElementResult_h
#define mozilla_SurfaceFromElementResult_h
#include "gfxTypes.h"
#include "mozilla/gfx/Point.h"
#include "nsCOMPtr.h"
#include <cstdint>
class imgIContainer;
class imgIRequest;
class nsIPrincipal;
class nsLayoutUtils;
namespace mozilla {
namespace dom {
class CanvasRenderingContext2D;
}
namespace gfx {
class SourceSurface;
}
namespace layers {
class Image;
}
struct DirectDrawInfo {
/* imgIContainer to directly draw to a context */
nsCOMPtr<imgIContainer> mImgContainer;
/* which frame to draw */
uint32_t mWhichFrame;
/* imgIContainer flags to use when drawing */
uint32_t mDrawingFlags;
};
struct SurfaceFromElementResult {
friend class mozilla::dom::CanvasRenderingContext2D;
friend class ::nsLayoutUtils;
/* If SFEResult contains a valid surface, it either mLayersImage or
* mSourceSurface will be non-null, and GetSourceSurface() will not be null.
*
* For valid surfaces, mSourceSurface may be null if mLayersImage is
* non-null, but GetSourceSurface() will create mSourceSurface from
* mLayersImage when called.
*/
/* Video elements (at least) often are already decoded as layers::Images. */
RefPtr<mozilla::layers::Image> mLayersImage;
protected:
/* GetSourceSurface() fills this and returns its non-null value if this
* SFEResult was successful. */
RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
public:
/* Contains info for drawing when there is no mSourceSurface. */
DirectDrawInfo mDrawInfo;
/* The size of the surface */
mozilla::gfx::IntSize mSize;
/* The size the surface is intended to be rendered at */
mozilla::gfx::IntSize mIntrinsicSize;
/* The principal associated with the element whose surface was returned.
If there is a surface, this will never be null. */
nsCOMPtr<nsIPrincipal> mPrincipal;
/* The image request, if the element is an nsIImageLoadingContent */
nsCOMPtr<imgIRequest> mImageRequest;
/* True if cross-origins redirects have been done in order to load this
* resource */
bool mHadCrossOriginRedirects;
/* Whether the element was "write only", that is, the bits should not be
* exposed to content */
bool mIsWriteOnly;
/* Whether the element was still loading. Some consumers need to handle
this case specially. */
bool mIsStillLoading;
/* Whether the element has a valid size. */
bool mHasSize;
/* Whether the element used CORS when loading. */
bool mCORSUsed;
gfxAlphaType mAlphaType;
// Methods:
SurfaceFromElementResult();
// Gets mSourceSurface, or makes a SourceSurface from mLayersImage.
const RefPtr<mozilla::gfx::SourceSurface>& GetSourceSurface();
};
} // namespace mozilla
#endif // mozilla_SurfaceFromElementResult_h

View File

@ -8,6 +8,7 @@
#include "mozilla/dom/EventTarget.h"
#include "mozilla/PresShell.h"
#include "nsIFrame.h"
#include "nsLayoutUtils.h"
#include "nsView.h"
#include "PositionedEventTargeting.h"
@ -107,15 +108,6 @@ nsIFrame* TouchManager::SetupTarget(WidgetTouchEvent* aEvent,
return aFrame;
}
uint32_t flags = 0;
// Setting this flag will skip the scrollbars on the root frame from
// participating in hit-testing, and we only want that to happen on
// zoomable platforms (for now).
dom::Document* doc = aFrame->PresContext()->Document();
if (nsLayoutUtils::AllowZoomingForDocument(doc)) {
flags |= INPUT_IGNORE_ROOT_SCROLL_FRAME;
}
nsIFrame* target = aFrame;
for (int32_t i = aEvent->mTouches.Length(); i;) {
--i;
@ -124,9 +116,10 @@ nsIFrame* TouchManager::SetupTarget(WidgetTouchEvent* aEvent,
int32_t id = touch->Identifier();
if (!TouchManager::HasCapturedTouch(id)) {
// find the target for this touch
RelativeTo relativeTo{aFrame};
nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(
aEvent, touch->mRefPoint, aFrame);
target = FindFrameTargetedByInputEvent(aEvent, aFrame, eventPoint, flags);
aEvent, touch->mRefPoint, relativeTo);
target = FindFrameTargetedByInputEvent(aEvent, relativeTo, eventPoint);
if (target) {
nsCOMPtr<nsIContent> targetContent;
target->GetContentForEvent(aEvent, getter_AddRefs(targetContent));

View File

@ -136,7 +136,7 @@ Maybe<gfx::IntRectTyped<TargetUnits>> ViewAs(
}
return Nothing();
}
// Unlike the other functions in this category, this function takes the
// Unlike the other functions in this category, these functions take the
// target matrix type, rather than its source and target unit types, as
// the explicit template argument, so an example invocation is:
// ViewAs<ScreenToLayerMatrix4x4>(otherTypedMatrix, justification)
@ -150,6 +150,28 @@ TargetMatrix ViewAs(const gfx::Matrix4x4Typed<SourceMatrixSourceUnits,
PixelCastJustification) {
return TargetMatrix::FromUnknownMatrix(aMatrix.ToUnknownMatrix());
}
template <class TargetMatrix, class SourceMatrixSourceUnits,
class SourceMatrixTargetUnits>
Maybe<TargetMatrix> ViewAs(
const Maybe<gfx::Matrix4x4Typed<SourceMatrixSourceUnits,
SourceMatrixTargetUnits>>& aMatrix,
PixelCastJustification) {
if (aMatrix.isSome()) {
return Some(TargetMatrix::FromUnknownMatrix(aMatrix->ToUnknownMatrix()));
}
return Nothing();
}
// A non-member overload of ToUnknownMatrix() for use on a Maybe<Matrix>.
// We can't make this a member because we can't inject a member into Maybe.
template <typename SourceUnits, typename TargetUnits>
Maybe<gfx::Matrix4x4> ToUnknownMatrix(
const Maybe<gfx::Matrix4x4Typed<SourceUnits, TargetUnits>>& aMatrix) {
if (aMatrix.isSome()) {
return Some(aMatrix->ToUnknownMatrix());
}
return Nothing();
}
// Convenience functions for casting untyped entities to typed entities.
// Using these functions does not require a justification, but once we convert

View File

@ -5,6 +5,8 @@
#ifndef MOZ_UNITS_H_
#define MOZ_UNITS_H_
#include <type_traits>
#include "mozilla/gfx/Coord.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Rect.h"
@ -15,12 +17,11 @@
#include "nsRect.h"
#include "nsRegion.h"
#include "mozilla/AppUnits.h"
#include "mozilla/TypeTraits.h"
namespace mozilla {
template <typename T>
struct IsPixel : FalseType {};
struct IsPixel : std::false_type {};
// See struct declaration for a description of each unit type.
struct CSSPixel;
@ -34,23 +35,23 @@ struct DesktopPixel;
struct ImagePixel;
template <>
struct IsPixel<CSSPixel> : TrueType {};
struct IsPixel<CSSPixel> : std::true_type {};
template <>
struct IsPixel<LayoutDevicePixel> : TrueType {};
struct IsPixel<LayoutDevicePixel> : std::true_type {};
template <>
struct IsPixel<LayerPixel> : TrueType {};
struct IsPixel<LayerPixel> : std::true_type {};
template <>
struct IsPixel<CSSTransformedLayerPixel> : TrueType {};
struct IsPixel<CSSTransformedLayerPixel> : std::true_type {};
template <>
struct IsPixel<RenderTargetPixel> : TrueType {};
struct IsPixel<RenderTargetPixel> : std::true_type {};
template <>
struct IsPixel<ImagePixel> : TrueType {};
struct IsPixel<ImagePixel> : std::true_type {};
template <>
struct IsPixel<ScreenPixel> : TrueType {};
struct IsPixel<ScreenPixel> : std::true_type {};
template <>
struct IsPixel<ParentLayerPixel> : TrueType {};
struct IsPixel<ParentLayerPixel> : std::true_type {};
template <>
struct IsPixel<DesktopPixel> : TrueType {};
struct IsPixel<DesktopPixel> : std::true_type {};
typedef gfx::CoordTyped<CSSPixel> CSSCoord;
typedef gfx::IntCoordTyped<CSSPixel> CSSIntCoord;
@ -221,8 +222,13 @@ typedef gfx::ScaleFactors2D<ParentLayerPixel, ScreenPixel>
typedef gfx::ScaleFactors2D<ParentLayerPixel, ParentLayerPixel>
ParentLayerToParentLayerScale2D;
typedef gfx::Matrix4x4Typed<CSSPixel, CSSPixel> CSSToCSSMatrix4x4;
typedef gfx::Matrix4x4Typed<LayoutDevicePixel, LayoutDevicePixel>
LayoutDeviceToLayoutDeviceMatrix4x4;
#ifdef MOZ_BUILD_WEBRENDER
typedef gfx::Matrix4x4Typed<LayoutDevicePixel, ParentLayerPixel>
LayoutDeviceToParentLayerMatrix4x4;
#endif
typedef gfx::Matrix4x4Typed<LayerPixel, ParentLayerPixel>
LayerToParentLayerMatrix4x4;
typedef gfx::Matrix4x4Typed<LayerPixel, ScreenPixel> LayerToScreenMatrix4x4;
@ -822,6 +828,11 @@ struct CoordOfImpl<gfx::IntRectTyped<Units>> {
typedef gfx::IntCoordTyped<Units> Type;
};
template <typename Units>
struct CoordOfImpl<gfx::SizeTyped<Units>> {
typedef gfx::CoordTyped<Units> Type;
};
template <typename T>
using CoordOf = typename CoordOfImpl<T>::Type;

View File

@ -0,0 +1,225 @@
/* 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/. */
#include "mozilla/PresShell.h"
#include "mozilla/ViewportFrame.h"
#include "mozilla/ViewportUtils.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/InputAPZContext.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
#include "nsIContent.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsLayoutUtils.h"
#include "nsQueryFrame.h"
#include "nsStyleStruct.h"
namespace mozilla {
using layers::APZCCallbackHelper;
using layers::InputAPZContext;
using layers::ScrollableLayerGuid;
template <typename Units>
gfx::Matrix4x4Typed<Units, Units> ViewportUtils::GetVisualToLayoutTransform(
ScrollableLayerGuid::ViewID aScrollId) {
static_assert(
std::is_same_v<Units, CSSPixel> ||
std::is_same_v<Units, LayoutDevicePixel>,
"GetCallbackTransform() may only be used with CSS or LayoutDevice units");
if (aScrollId == ScrollableLayerGuid::NULL_SCROLL_ID) {
return {};
}
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aScrollId);
if (!content || !content->GetPrimaryFrame()) {
return {};
}
// First, scale inversely by the root content document's pres shell
// resolution to cancel the scale-to-resolution transform that the
// compositor adds to the layer with the pres shell resolution. The points
// sent to Gecko by APZ don't have this transform unapplied (unlike other
// compositor-side transforms) because Gecko needs it applied when hit
// testing against content that's conceptually outside the resolution,
// such as scrollbars.
float resolution = 1.0f;
if (PresShell* presShell =
APZCCallbackHelper::GetRootContentDocumentPresShellForContent(
content)) {
resolution = presShell->GetResolution();
}
// Now apply the callback-transform. This is only approximately correct,
// see the comment on GetCumulativeApzCallbackTransform for details.
gfx::PointTyped<Units> transform;
CSSPoint transformCSS = nsLayoutUtils::GetCumulativeApzCallbackTransform(
content->GetPrimaryFrame());
if constexpr (std::is_same_v<Units, CSSPixel>) {
transform = transformCSS;
} else { // Units == LayoutDevicePixel
transform = transformCSS *
content->GetPrimaryFrame()->PresContext()->CSSToDevPixelScale();
}
return gfx::Matrix4x4Typed<Units, Units>::Scaling(1 / resolution,
1 / resolution, 1)
.PostTranslate(transform.x, transform.y, 0);
}
CSSToCSSMatrix4x4 GetVisualToLayoutTransform(PresShell* aContext) {
ScrollableLayerGuid::ViewID targetScrollId =
InputAPZContext::GetTargetLayerGuid().mScrollId;
if (targetScrollId == ScrollableLayerGuid::NULL_SCROLL_ID) {
if (nsIFrame* rootScrollFrame = aContext->GetRootScrollFrame()) {
targetScrollId =
nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent());
}
}
return ViewportUtils::GetVisualToLayoutTransform(targetScrollId);
}
nsPoint ViewportUtils::VisualToLayout(const nsPoint& aPt, PresShell* aContext) {
auto visualToLayout = mozilla::GetVisualToLayoutTransform(aContext);
CSSPoint cssPt = CSSPoint::FromAppUnits(aPt);
cssPt = visualToLayout.TransformPoint(cssPt);
return CSSPoint::ToAppUnits(cssPt);
}
nsRect ViewportUtils::VisualToLayout(const nsRect& aRect, PresShell* aContext) {
auto visualToLayout = mozilla::GetVisualToLayoutTransform(aContext);
CSSRect cssRect = CSSRect::FromAppUnits(aRect);
cssRect = visualToLayout.TransformBounds(cssRect);
nsRect result = CSSRect::ToAppUnits(cssRect);
// In hit testing codepaths, the input rect often has dimensions of one app
// units. If we are zoomed in enough, the rounded size of the output rect
// can be zero app units, which will fail to Intersect() with anything, and
// therefore cause hit testing to fail. To avoid this, we expand the output
// rect to one app units.
if (!aRect.IsEmpty() && result.IsEmpty()) {
result.width = 1;
result.height = 1;
}
return result;
}
nsPoint ViewportUtils::LayoutToVisual(const nsPoint& aPt, PresShell* aContext) {
auto visualToLayout = mozilla::GetVisualToLayoutTransform(aContext);
CSSPoint cssPt = CSSPoint::FromAppUnits(aPt);
auto transformed = visualToLayout.Inverse().TransformPoint(cssPt);
return CSSPoint::ToAppUnits(transformed);
}
LayoutDevicePoint ViewportUtils::DocumentRelativeLayoutToVisual(
const LayoutDevicePoint& aPoint, PresShell* aShell) {
ScrollableLayerGuid::ViewID targetScrollId =
nsLayoutUtils::ScrollIdForRootScrollFrame(aShell->GetPresContext());
auto visualToLayout =
ViewportUtils::GetVisualToLayoutTransform<LayoutDevicePixel>(
targetScrollId);
return visualToLayout.Inverse().TransformPoint(aPoint);
}
LayoutDeviceRect ViewportUtils::DocumentRelativeLayoutToVisual(
const LayoutDeviceRect& aRect, PresShell* aShell) {
ScrollableLayerGuid::ViewID targetScrollId =
nsLayoutUtils::ScrollIdForRootScrollFrame(aShell->GetPresContext());
auto visualToLayout =
ViewportUtils::GetVisualToLayoutTransform<LayoutDevicePixel>(
targetScrollId);
return visualToLayout.Inverse().TransformBounds(aRect);
}
CSSRect ViewportUtils::DocumentRelativeLayoutToVisual(const CSSRect& aRect,
PresShell* aShell) {
ScrollableLayerGuid::ViewID targetScrollId =
nsLayoutUtils::ScrollIdForRootScrollFrame(aShell->GetPresContext());
auto visualToLayout =
ViewportUtils::GetVisualToLayoutTransform(targetScrollId);
return visualToLayout.Inverse().TransformBounds(aRect);
}
template <class LDPointOrRect>
LDPointOrRect ConvertToScreenRelativeVisual(const LDPointOrRect& aInput,
nsPresContext* aCtx) {
MOZ_ASSERT(aCtx);
LDPointOrRect layoutToVisual(aInput);
nsIFrame* prevRootFrame = nullptr;
nsPresContext* prevCtx = nullptr;
// Walk up to the rootmost prescontext, transforming as we go.
for (nsPresContext* ctx = aCtx; ctx; ctx = ctx->GetParentPresContext()) {
PresShell* shell = ctx->PresShell();
nsIFrame* rootFrame = shell->GetRootFrame();
if (prevRootFrame) {
// Convert layoutToVisual from being relative to `prevRootFrame`
// to being relative to `rootFrame` (layout space).
nscoord apd = prevCtx->AppUnitsPerDevPixel();
nsPoint offset = prevRootFrame->GetOffsetToCrossDoc(rootFrame, apd);
layoutToVisual += LayoutDevicePoint::FromAppUnits(offset, apd);
}
if (shell->GetResolution() != 1.0) {
// Found the APZ zoom root, so do the layout -> visual conversion.
layoutToVisual =
ViewportUtils::DocumentRelativeLayoutToVisual(layoutToVisual, shell);
}
prevRootFrame = rootFrame;
prevCtx = ctx;
}
// Then we do the conversion from the rootmost presContext's root frame (in
// visual space) to screen space.
LayoutDeviceIntRect rootScreenRect =
LayoutDeviceIntRect::FromAppUnitsToNearest(
prevRootFrame->GetScreenRectInAppUnits(),
prevCtx->AppUnitsPerDevPixel());
return layoutToVisual + rootScreenRect.TopLeft();
}
LayoutDevicePoint ViewportUtils::ToScreenRelativeVisual(
const LayoutDevicePoint& aPt, nsPresContext* aCtx) {
return ConvertToScreenRelativeVisual(aPt, aCtx);
}
LayoutDeviceRect ViewportUtils::ToScreenRelativeVisual(
const LayoutDeviceRect& aRect, nsPresContext* aCtx) {
return ConvertToScreenRelativeVisual(aRect, aCtx);
}
// Definitions of the two explicit instantiations forward declared in the header
// file. This causes code for these instantiations to be emitted into the object
// file for ViewportUtils.cpp.
template CSSToCSSMatrix4x4 ViewportUtils::GetVisualToLayoutTransform<CSSPixel>(
ScrollableLayerGuid::ViewID);
template LayoutDeviceToLayoutDeviceMatrix4x4
ViewportUtils::GetVisualToLayoutTransform<LayoutDevicePixel>(
ScrollableLayerGuid::ViewID);
const nsIFrame* ViewportUtils::IsZoomedContentRoot(const nsIFrame* aFrame) {
if (!aFrame) {
return nullptr;
}
if (aFrame->Type() == LayoutFrameType::Canvas ||
aFrame->Type() == LayoutFrameType::PageSequence) {
nsIScrollableFrame* sf = do_QueryFrame(aFrame->GetParent());
if (sf && sf->IsRootScrollFrameOfDocument() &&
aFrame->PresContext()->IsRootContentDocument()) {
return aFrame->GetParent();
}
} else if (aFrame->StyleDisplay()->mPosition ==
StylePositionProperty::Fixed) {
if (ViewportFrame* viewportFrame = do_QueryFrame(aFrame->GetParent())) {
if (viewportFrame->PresContext()->IsRootContentDocument()) {
return viewportFrame->PresShell()->GetRootScrollFrame();
}
}
}
return nullptr;
}
} // namespace mozilla

110
layout/base/ViewportUtils.h Normal file
View File

@ -0,0 +1,110 @@
/* 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/. */
#ifndef mozilla_ViewportUtils_h
#define mozilla_ViewportUtils_h
#include "Units.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
class nsIFrame;
namespace mozilla {
class PresShell;
class ViewportUtils {
public:
/* Return a transform to be applied to the coordinates of input events
targeting content inside the scroll frame identified by |aScrollId|, which
converts from "visual coordinates" (which are the coordinates events have
when they arrive from APZ) to "layout coordinates" (which are the
coordinates used in most places by layout code). The transform has two
components:
1. The pres shell resolution, representing the pinch-zoom scale
(if the scroll frame |aScrollId| is inside the resolution, which
is most of the time).
2. A translation representing async scrolling. This can contain:
- For any scroll frame, a scroll component resulting from the main
thread incompletely applying an APZ-requested scroll position.
- For the RCD-RSF only, a persistent component representing the
offset of the visual viewport relative to the layout viewport.
The translation is accumulated for all scroll frames form |aScrollId|
up to the root, using values populated in
APZCCallbackHelper::UpdateCallbackTransform. See that method's
documentation for additional details. */
template <typename Units = CSSPixel>
static gfx::Matrix4x4Typed<Units, Units> GetVisualToLayoutTransform(
layers::ScrollableLayerGuid::ViewID aScrollId);
/* The functions below apply GetVisualToLayoutTransform() or its inverse
* to various quantities.
*
* To determine the appropriate scroll id to pass into
* GetVisualToLayoutTransform(), these functions prefer to use the one
* from InputAPZContext::GetTargetLayerGuid() if one is available.
* If one is not available, they use the scroll id of the root scroll
* frame of the pres shell passed in as |aContext| as a fallback.
*/
static nsPoint VisualToLayout(const nsPoint& aPt, PresShell* aContext);
static nsRect VisualToLayout(const nsRect& aRect, PresShell* aContext);
static nsPoint LayoutToVisual(const nsPoint& aPt, PresShell* aContext);
/*
* These functions convert the point/rect from layout to visual space
* by applying the inverse of GetLayoutToVisualTransform() of the root
* scrollframe of provided presShell.
*/
static LayoutDevicePoint DocumentRelativeLayoutToVisual(
const LayoutDevicePoint& aPoint, PresShell* aShell);
static LayoutDeviceRect DocumentRelativeLayoutToVisual(
const LayoutDeviceRect& aRect, PresShell* aShell);
static CSSRect DocumentRelativeLayoutToVisual(const CSSRect& aRect,
PresShell* aShell);
/*
* These convert aPt/aRect, which is the layout space of aCtx, into a
* screen-relative visual-space quantity. Formally, we can think of the input
* as being in RelativeTo{aCtx->PresShell()->GetRootFrame(),
* ViewportType::Layout} space. And then the function iterates up the chain of
* presContexts, transforming the point along, until it gets to the
* RelativeTo{aCtx->GetRootPresContext()->PresShell()->GetRootFrame(),
* ViewportType::Visual} space. Then it further transforms it into a
* screen-relative space. Unlike the GetTransformToAncestor family of helper
* methods, this transformation does NOT include CSS transforms. Also, unlike
* other ViewportUtils methods, the input is relative to `aCtx` which might be
* a sub-shell of the presShell with the resolution.
*/
static LayoutDevicePoint ToScreenRelativeVisual(const LayoutDevicePoint& aPt,
nsPresContext* aCtx);
static LayoutDeviceRect ToScreenRelativeVisual(const LayoutDeviceRect& aRect,
nsPresContext* aCtx);
/**
* Returns non-null if |aFrame| is inside the async zoom container but its
* parent frame is not, thereby making |aFrame| a root of a subtree of
* frames representing content that is zoomed in. The value returned in such
* cases is the root scroll frame inside the async zoom container.
* Callers use this to identify points during frame tree traversal where the
* visual-to-layout transform needs to be applied.
*/
static const nsIFrame* IsZoomedContentRoot(const nsIFrame* aFrame);
};
// Forward declare explicit instantiations of GetVisualToLayoutTransform() for
// CSSPixel and LayoutDevicePixel, the only two types it gets used with.
// These declarations promise to callers in any translation unit that _some_
// translation unit (in this case, ViewportUtils.cpp) will contain the
// definitions of these instantiations. This allows us to keep the definition
// out-of-line in the source.
extern template CSSToCSSMatrix4x4 ViewportUtils::GetVisualToLayoutTransform<
CSSPixel>(layers::ScrollableLayerGuid::ViewID);
extern template LayoutDeviceToLayoutDeviceMatrix4x4
ViewportUtils::GetVisualToLayoutTransform<LayoutDevicePixel>(
layers::ScrollableLayerGuid::ViewID);
} // namespace mozilla
#endif /* mozilla_ViewportUtils_h */

View File

@ -22,23 +22,26 @@
#include "Units.h"
#include "UnitTransforms.h"
#define ZCC_LOG(...)
// #define ZCC_LOG(...) printf_stderr("ZCC: " __VA_ARGS__)
static mozilla::LazyLogModule sApzZoomLog("apz.zoom");
#define ZCC_LOG(...) MOZ_LOG(sApzZoomLog, LogLevel::Debug, (__VA_ARGS__))
NS_IMPL_ISUPPORTS(ZoomConstraintsClient, nsIDOMEventListener, nsIObserver)
#define DOM_META_ADDED NS_LITERAL_STRING("DOMMetaAdded")
#define DOM_META_CHANGED NS_LITERAL_STRING("DOMMetaChanged")
#define FULLSCREEN_CHANGED NS_LITERAL_STRING("fullscreenchange")
#define BEFORE_FIRST_PAINT NS_LITERAL_CSTRING("before-first-paint")
#define NS_PREF_CHANGED NS_LITERAL_CSTRING("nsPref:changed")
#define DOM_META_ADDED u"DOMMetaAdded"_ns
#define DOM_META_CHANGED u"DOMMetaChanged"_ns
#define FULLSCREEN_CHANGED u"fullscreenchange"_ns
#define BEFORE_FIRST_PAINT "before-first-paint"_ns
#define NS_PREF_CHANGED "nsPref:changed"_ns
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
ZoomConstraintsClient::ZoomConstraintsClient()
: mDocument(nullptr), mPresShell(nullptr) {}
: mDocument(nullptr),
mPresShell(nullptr),
mZoomConstraints(false, false, CSSToParentLayerScale(1.f),
CSSToParentLayerScale(1.f)) {}
ZoomConstraintsClient::~ZoomConstraintsClient() = default;
@ -184,6 +187,9 @@ static mozilla::layers::ZoomConstraints ComputeZoomConstraintsFromViewportInfo(
}
void ZoomConstraintsClient::RefreshZoomConstraints() {
mZoomConstraints = ZoomConstraints(false, false, CSSToParentLayerScale(1.f),
CSSToParentLayerScale(1.f));
nsIWidget* widget = GetWidget(mPresShell);
if (!widget) {
return;
@ -207,22 +213,22 @@ void ZoomConstraintsClient::RefreshZoomConstraints() {
nsViewportInfo viewportInfo = mDocument->GetViewportInfo(ViewAs<ScreenPixel>(
screenSize, PixelCastJustification::LayoutDeviceIsScreenForBounds));
mozilla::layers::ZoomConstraints zoomConstraints =
mZoomConstraints =
ComputeZoomConstraintsFromViewportInfo(viewportInfo, mDocument);
if (mDocument->Fullscreen()) {
ZCC_LOG("%p is in fullscreen, disallowing zooming\n", this);
zoomConstraints.mAllowZoom = false;
zoomConstraints.mAllowDoubleTapZoom = false;
mZoomConstraints.mAllowZoom = false;
mZoomConstraints.mAllowDoubleTapZoom = false;
}
if (zoomConstraints.mAllowDoubleTapZoom) {
if (mZoomConstraints.mAllowDoubleTapZoom) {
// If the CSS viewport is narrower than the screen (i.e. width <=
// device-width) then we disable double-tap-to-zoom behaviour.
CSSToLayoutDeviceScale scale =
mPresShell->GetPresContext()->CSSToDevPixelScale();
if ((viewportInfo.GetSize() * scale).width <= screenSize.width) {
zoomConstraints.mAllowDoubleTapZoom = false;
mZoomConstraints.mAllowDoubleTapZoom = false;
}
}
@ -232,8 +238,8 @@ void ZoomConstraintsClient::RefreshZoomConstraints() {
if (nsIScrollableFrame* rcdrsf =
mPresShell->GetRootScrollFrameAsScrollable()) {
ZCC_LOG("Notifying RCD-RSF that it is zoomable: %d\n",
zoomConstraints.mAllowZoom);
rcdrsf->SetZoomableByAPZ(zoomConstraints.mAllowZoom);
mZoomConstraints.mAllowZoom);
rcdrsf->SetZoomableByAPZ(mZoomConstraints.mAllowZoom);
}
ScrollableLayerGuid newGuid(LayersId{0}, presShellId, viewId);
@ -246,6 +252,6 @@ void ZoomConstraintsClient::RefreshZoomConstraints() {
}
mGuid = Some(newGuid);
ZCC_LOG("Sending constraints %s in %p for { %u, %" PRIu64 " }\n",
Stringify(zoomConstraints).c_str(), this, presShellId, viewId);
widget->UpdateZoomConstraints(presShellId, viewId, Some(zoomConstraints));
Stringify(mZoomConstraints).c_str(), this, presShellId, viewId);
widget->UpdateZoomConstraints(presShellId, viewId, Some(mZoomConstraints));
}

View File

@ -5,8 +5,8 @@
#ifndef ZoomConstraintsClient_h_
#define ZoomConstraintsClient_h_
#include "mozilla/dom/Document.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
#include "mozilla/layers/ZoomConstraints.h"
#include "mozilla/Maybe.h"
#include "nsCOMPtr.h"
#include "nsIDOMEventListener.h"
@ -37,6 +37,8 @@ class ZoomConstraintsClient final : public nsIDOMEventListener,
void Destroy();
void ScreenSizeChanged();
bool GetAllowZoom() const { return mZoomConstraints.mAllowZoom; }
private:
void RefreshZoomConstraints();
@ -45,6 +47,7 @@ class ZoomConstraintsClient final : public nsIDOMEventListener,
mozilla::PresShell* MOZ_NON_OWNING_REF mPresShell;
nsCOMPtr<mozilla::dom::EventTarget> mEventTarget;
mozilla::Maybe<mozilla::layers::ScrollableLayerGuid> mGuid;
mozilla::layers::ZoomConstraints mZoomConstraints;
};
#endif

View File

@ -0,0 +1,11 @@
<html>
<head>
<style>
* { column-count: 1 }
</style>
</head>
</html>
<body>
<div style="">
<fieldset style="transform-style:preserve-3d">
<fieldset style="position:fixed">

View File

@ -0,0 +1,7 @@
<script>
window.onload = () => {
document.getElementById('a').appendChild(document.createElement('col'))
}
</script>
<fieldset id='a'>
<legend>

View File

@ -223,7 +223,7 @@ load 412651-1.html
load 413587-1.svg
load 414058-1.html
load 415503.xhtml
load 416107.xhtml
asserts(1-1) load 416107.xhtml # bug 489100, ASSERTION: Out-of-flow frame got reflowed before its placeholder
HTTP load 419985.html
load 420031-1.html
load 420213-1.html
@ -401,7 +401,7 @@ load 709536-1.xhtml
load 722137.html
load 725535.html
load 727601.html
skip-if(Android) asserts(0-2) pref(dom.disable_open_during_load,false) load 735943.html # the assertion is bug 735966, for android bug 760271
asserts(0-2) pref(dom.disable_open_during_load,false) load 735943.html # the assertion is bug 735966
asserts(0-2) load 736389-1.xhtml # sometimes the above assertions are delayed and is reported on this test instead
load 736924-1.html
load 749816-1.html
@ -482,7 +482,7 @@ load 1308848-2.html
load 1338772-1.html
load 1340571.html
pref(dom.animations-api.implicit-keyframes.enabled,true) load 1343139-1.html
asserts(0-1) asserts-if(Android,1-4) load 1343606.html # bug 1343948
asserts-if(Android,0-3) load 1343606.html # bug 1642521
load 1343937.html
load 1352380.html
load 1362423-1.html
@ -511,6 +511,7 @@ load 1414303.html
load 1419762.html
load 1419802.html
load 1420533.html
load 1422908.html
load 1423216.html
load 1425893.html
load 1425959.html
@ -587,3 +588,4 @@ load 1586600.html
load 1599518.html
load 1599532.html
pref(layout.accessiblecaret.enabled,true) load 1606492.html
load 1690163.html

View File

@ -58,6 +58,7 @@ EXPORTS += [
'nsPresContextInlines.h',
'nsQuoteList.h',
'nsRefreshDriver.h',
'nsRefreshObservers.h',
'nsStyleChangeList.h',
'nsStyleSheetService.h',
'StackArena.h',
@ -71,25 +72,31 @@ EXPORTS += [
EXPORTS.mozilla += [
'AccessibleCaretEventHub.h',
'ArenaObjectID.h',
'DisplayPortUtils.h',
'GeckoMVMContext.h',
'GeometryUtils.h',
'MotionPathUtils.h',
'MVMContext.h',
'OverflowChangedTracker.h',
'PositionedEventTargeting.h',
'PresShell.h',
'PresShellForwards.h',
'PresShellInlines.h',
'RelativeTo.h',
'RestyleManager.h',
'ScrollStyles.h',
'ScrollTypes.h',
'ShapeUtils.h',
'StaticPresData.h',
'SurfaceFromElementResult.h',
'ViewportUtils.h',
]
UNIFIED_SOURCES += [
'AccessibleCaret.cpp',
'AccessibleCaretEventHub.cpp',
'AccessibleCaretManager.cpp',
'DisplayPortUtils.cpp',
'GeckoMVMContext.cpp',
'GeometryUtils.cpp',
'LayoutLogging.cpp',
@ -121,6 +128,7 @@ UNIFIED_SOURCES += [
'StackArena.cpp',
'StaticPresData.cpp',
'TouchManager.cpp',
'ViewportUtils.cpp',
'ZoomConstraintsClient.cpp',
]
@ -141,7 +149,6 @@ LOCAL_INCLUDES += [
'../painting',
'../printing',
'../style',
'../svg',
'../tables',
'../xul',
'../xul/tree/',

View File

@ -74,8 +74,8 @@ static bool IsIsolateControl(char16_t aChar) {
// Returns 0 if no override control character is implied by this style.
static char16_t GetBidiOverride(ComputedStyle* aComputedStyle) {
const nsStyleVisibility* vis = aComputedStyle->StyleVisibility();
if ((vis->mWritingMode == NS_STYLE_WRITING_MODE_VERTICAL_RL ||
vis->mWritingMode == NS_STYLE_WRITING_MODE_VERTICAL_LR) &&
if ((vis->mWritingMode == StyleWritingModeProperty::VerticalRl ||
vis->mWritingMode == StyleWritingModeProperty::VerticalLr) &&
vis->mTextOrientation == StyleTextOrientation::Upright) {
return kLRO;
}

View File

@ -26,6 +26,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/PresShell.h"
#include "mozilla/PresShellInlines.h"
#include "mozilla/PrintedSheetFrame.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleSetInlines.h"
#include "mozilla/StaticPrefs_layout.h"
@ -118,8 +119,11 @@
#undef NOISY_FIRST_LETTER
#include "nsMathMLParts.h"
#include "mozilla/dom/SVGAnimationElement.h"
#include "mozilla/dom/SVGFilters.h"
#include "mozilla/dom/SVGTests.h"
#include "nsSVGUtils.h"
#include "mozilla/SVGGradientFrame.h"
#include "mozilla/SVGUtils.h"
#include "nsRefreshDriver.h"
#include "nsTextNode.h"
@ -353,7 +357,7 @@ static inline bool IsDisplayContents(const nsIContent* aContent) {
*/
static bool IsFrameForSVG(const nsIFrame* aFrame) {
return aFrame->IsFrameOfType(nsIFrame::eSVG) ||
nsSVGUtils::IsInSVGTextSubtree(aFrame);
SVGUtils::IsInSVGTextSubtree(aFrame);
}
static bool IsLastContinuationForColumnContent(const nsIFrame* aFrame) {
@ -712,6 +716,10 @@ class MOZ_STACK_CLASS nsFrameConstructorState {
// mode).
bool mCreatingExtraFrames;
// This keeps track of whether we have found a "rendered legend" for
// the current FieldSetFrame.
bool mHasRenderedLegend;
nsTArray<RefPtr<nsIContent>> mGeneratedContentWithInitializer;
// Constructor
@ -907,6 +915,7 @@ nsFrameConstructorState::nsFrameConstructorState(
mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
mHavePendingPopupgroup(false),
mCreatingExtraFrames(false),
mHasRenderedLegend(false),
mCurrentPendingBindingInsertionPoint(nullptr) {
#ifdef MOZ_XUL
nsIPopupContainer* popupContainer =
@ -1022,7 +1031,7 @@ nsContainerFrame* nsFrameConstructorState::GetGeometricParent(
// float to "none"? That's OK per CSS 2.1, as far as I can tell.
if (aContentParentFrame &&
nsSVGUtils::IsInSVGTextSubtree(aContentParentFrame)) {
SVGUtils::IsInSVGTextSubtree(aContentParentFrame)) {
return aContentParentFrame;
}
@ -1105,13 +1114,13 @@ AbsoluteFrameList* nsFrameConstructorState::GetOutOfFlowFrameList(
return &mPopupList;
}
#endif // MOZ_XUL
if (aCanBeFloated && aNewFrame->IsFloating()) {
const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
if (aCanBeFloated && disp->IsFloatingStyle()) {
*aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
return &mFloatedList;
}
if (aCanBePositioned) {
const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
if (disp->mTopLayer != StyleTopLayer::None) {
*aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
if (disp->mPosition == StylePositionProperty::Fixed) {
@ -1439,7 +1448,7 @@ static bool ShouldCreateImageFrameForContent(const Element& aElement,
return false;
}
Span<const StyleContentItem> items = content.AsItems().AsSpan();
return items.Length() == 1 && items[0].IsUrl();
return items.Length() == 1 && items[0].IsImage();
}
//----------------------------------------------------------------------
@ -1562,7 +1571,7 @@ already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGeneratedContent(
const Type type = item.tag;
switch (type) {
case Type::Url:
case Type::Image:
return GeneratedImageContent::Create(*mDocument, aContentIndex);
case Type::String:
@ -1613,8 +1622,7 @@ already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGeneratedContent(
auto initializer = MakeUnique<nsGenConInitializer>(
std::move(node), counterList, &nsCSSFrameConstructor::CountersDirty);
return CreateGenConTextNode(aState, EmptyString(),
std::move(initializer));
return CreateGenConTextNode(aState, u""_ns, std::move(initializer));
}
case Type::OpenQuote:
case Type::CloseQuote:
@ -1623,8 +1631,7 @@ already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGeneratedContent(
auto node = MakeUnique<nsQuoteNode>(type, aContentIndex);
auto initializer = MakeUnique<nsGenConInitializer>(
std::move(node), &mQuoteList, &nsCSSFrameConstructor::QuotesDirty);
return CreateGenConTextNode(aState, EmptyString(),
std::move(initializer));
return CreateGenConTextNode(aState, u""_ns, std::move(initializer));
}
case Type::MozAltContent: {
@ -2552,7 +2559,7 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
ViewportFrame [fixed-cb]
nsHTMLScrollFrame
nsCanvasFrame [abs-cb]
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
root element frame (nsBlockFrame, SVGOuterSVGFrame,
nsTableWrapperFrame, nsPlaceholderFrame)
Galley presentation, XUL
@ -2565,22 +2572,24 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
ViewportFrame
nsPageSequenceFrame
nsPageFrame
nsPageContentFrame [fixed-cb]
nsCanvasFrame [abs-cb]
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
nsTableWrapperFrame, nsPlaceholderFrame)
PrintedSheetFrame
nsPageFrame
nsPageContentFrame [fixed-cb]
nsCanvasFrame [abs-cb]
root element frame (nsBlockFrame, SVGOuterSVGFrame,
nsTableWrapperFrame, nsPlaceholderFrame)
Print-preview presentation, non-XUL
ViewportFrame
nsHTMLScrollFrame
nsPageSequenceFrame
nsPageFrame
nsPageContentFrame [fixed-cb]
nsCanvasFrame [abs-cb]
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
nsTableWrapperFrame, nsPlaceholderFrame)
PrintedSheetFrame
nsPageFrame
nsPageContentFrame [fixed-cb]
nsCanvasFrame [abs-cb]
root element frame (nsBlockFrame, SVGOuterSVGFrame,
nsTableWrapperFrame, nsPlaceholderFrame)
Print/print preview of XUL is not supported.
[fixed-cb]: the default containing block for fixed-pos content
@ -2634,7 +2643,6 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
rootFrame = mPageSequenceFrame =
NS_NewPageSequenceFrame(mPresShell, viewportPseudoStyle);
rootPseudo = PseudoStyleType::pageSequence;
rootFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
}
// --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
@ -2716,13 +2724,19 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
}
if (isPaginated) {
// Create the first page
// Set the initial child lists
// Create the first printed sheet frame, as the sole child (for now) of our
// page sequence frame (rootFrame).
auto* printedSheetFrame =
ConstructPrintedSheetFrame(mPresShell, rootFrame, nullptr);
SetInitialSingleChild(rootFrame, printedSheetFrame);
// Create the first page, as the sole child (for now) of the printed sheet
// frame that we just created.
nsContainerFrame* canvasFrame;
nsContainerFrame* pageFrame =
ConstructPageFrame(mPresShell, rootFrame, nullptr, canvasFrame);
ConstructPageFrame(mPresShell, printedSheetFrame, nullptr, canvasFrame);
pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
SetInitialSingleChild(rootFrame, pageFrame);
SetInitialSingleChild(printedSheetFrame, pageFrame);
// The eventual parent of the document element frame.
// XXX should this be set for every new page (in ConstructPageFrame)?
@ -2759,15 +2773,28 @@ void nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(
aFrameList);
}
PrintedSheetFrame* nsCSSFrameConstructor::ConstructPrintedSheetFrame(
PresShell* aPresShell, nsContainerFrame* aParentFrame,
nsIFrame* aPrevSheetFrame) {
RefPtr<ComputedStyle> printedSheetPseudoStyle =
aPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
PseudoStyleType::printedSheet);
auto* printedSheetFrame =
NS_NewPrintedSheetFrame(aPresShell, printedSheetPseudoStyle);
printedSheetFrame->Init(nullptr, aParentFrame, aPrevSheetFrame);
return printedSheetFrame;
}
nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
PresShell* aPresShell, nsContainerFrame* aParentFrame,
nsIFrame* aPrevPageFrame, nsContainerFrame*& aCanvasFrame) {
ComputedStyle* parentComputedStyle = aParentFrame->Style();
ServoStyleSet* styleSet = aPresShell->StyleSet();
RefPtr<ComputedStyle> pagePseudoStyle;
pagePseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
PseudoStyleType::page, parentComputedStyle);
RefPtr<ComputedStyle> pagePseudoStyle =
styleSet->ResolveNonInheritingAnonymousBoxStyle(PseudoStyleType::page);
nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
@ -2776,8 +2803,8 @@ nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
RefPtr<ComputedStyle> pageContentPseudoStyle;
pageContentPseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
PseudoStyleType::pageContent, pagePseudoStyle);
pageContentPseudoStyle = styleSet->ResolveNonInheritingAnonymousBoxStyle(
PseudoStyleType::pageContent);
nsContainerFrame* pageContentFrame =
NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
@ -2791,6 +2818,8 @@ nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
}
pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
if (!prevPageContentFrame) {
// The canvas is an inheriting anon box, so needs to be "owned" by the page
// content.
pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
}
SetInitialSingleChild(pageFrame, pageContentFrame);
@ -3061,11 +3090,6 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
PseudoStyleType::scrolledContent, false, scrollFrame);
}
nsContainerFrame* absPosContainer = nullptr;
if (fieldsetFrame->IsAbsPosContainingBlock()) {
absPosContainer = fieldsetFrame;
}
// Create the inner ::-moz-fieldset-content frame.
nsContainerFrame* contentFrameTop;
nsContainerFrame* contentFrame;
@ -3092,9 +3116,6 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
if (fieldsetContentStyle->StyleColumn()->IsColumnContainerStyle()) {
contentFrameTop = BeginBuildingColumns(
aState, content, parent, contentFrame, fieldsetContentStyle);
if (absPosContainer) {
absPosContainer = contentFrameTop;
}
} else {
// No need to create column container. Initialize content frame.
InitAndRestoreFrame(aState, content, parent, contentFrame);
@ -3112,40 +3133,21 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
nsFrameList childList;
contentFrameTop->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
if (absPosContainer) {
aState.PushAbsoluteContainingBlock(contentFrameTop, absPosContainer,
if (fieldsetFrame->IsAbsPosContainingBlock()) {
aState.PushAbsoluteContainingBlock(contentFrameTop, fieldsetFrame,
absoluteSaveState);
}
ProcessChildren(aState, content, computedStyle, contentFrame, true, childList,
true, aItem.mPendingBinding);
{
AutoRestore<bool> savedHasRenderedLegend(aState.mHasRenderedLegend);
aState.mHasRenderedLegend = false;
ProcessChildren(aState, content, computedStyle, contentFrame, true,
childList, true, aItem.mPendingBinding);
}
nsFrameList fieldsetKids;
fieldsetKids.AppendFrame(nullptr,
scrollFrame ? scrollFrame : contentFrameTop);
for (nsFrameList::Enumerator e(childList); !e.AtEnd(); e.Next()) {
nsIFrame* child = e.get();
nsContainerFrame* cif = child->GetContentInsertionFrame();
if (cif && cif->IsLegendFrame()) {
// We want the legend to be the first frame in the fieldset child list.
// That way the EventStateManager will do the right thing when tabbing
// from a selection point within the legend (bug 236071), which is
// used for implementing legend access keys (bug 81481).
// GetAdjustedParentFrame() below depends on this frame order.
childList.RemoveFrame(child);
// Make sure to reparent the legend so it has the fieldset as the parent.
fieldsetKids.InsertFrame(fieldsetFrame, nullptr, child);
// Legend is no longer in the multicol container. Remove the bit.
child->RemoveStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
if (scrollFrame) {
StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary(
child, contentFrame);
}
break;
}
}
if (!MayNeedToCreateColumnSpanSiblings(contentFrame, childList)) {
// Set the inner frame's initial child lists.
contentFrame->SetInitialChildList(kPrincipalList, childList);
@ -3171,10 +3173,10 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
FinishBuildingScrollFrame(scrollFrame, contentFrameTop);
}
// Set the outer frame's initial child list
fieldsetFrame->SetInitialChildList(kPrincipalList, fieldsetKids);
// We use AppendFrames here because the rendered legend will already
// be present in the principal child list if it exists.
fieldsetFrame->AppendFrames(nsIFrame::kNoReflowPrincipalList, fieldsetKids);
// Our new frame returned is the outer frame, which is the fieldset frame.
return fieldsetFrame;
}
@ -3267,9 +3269,8 @@ const nsCSSFrameConstructor::FrameConstructionData*
nsCSSFrameConstructor::FindTextData(const Text& aTextContent,
nsIFrame* aParentFrame) {
if (aParentFrame && IsFrameForSVG(aParentFrame)) {
nsIFrame* ancestorFrame =
nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
if (!ancestorFrame || !nsSVGUtils::IsInSVGTextSubtree(ancestorFrame)) {
nsIFrame* ancestorFrame = SVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
if (!ancestorFrame || !SVGUtils::IsInSVGTextSubtree(ancestorFrame)) {
return nullptr;
}
@ -3382,15 +3383,15 @@ nsCSSFrameConstructor::FindDataByTag(const Element& aElement,
#define COMPLEX_TAG_CREATE(_tag, _func) \
{ nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
static bool IsFrameForFieldSet(nsIFrame* aFrame) {
static nsFieldSetFrame* GetFieldSetFrameFor(nsIFrame* aFrame) {
auto pseudo = aFrame->Style()->GetPseudoType();
if (pseudo == PseudoStyleType::fieldsetContent ||
pseudo == PseudoStyleType::scrolledContent ||
pseudo == PseudoStyleType::columnSet ||
pseudo == PseudoStyleType::columnContent) {
return IsFrameForFieldSet(aFrame->GetParent());
return GetFieldSetFrameFor(aFrame->GetParent());
}
return aFrame->IsFieldSetFrame();
return do_QueryFrame(aFrame);
}
/* static */
@ -3399,25 +3400,11 @@ nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
nsIFrame* aParentFrame,
ComputedStyle& aStyle) {
MOZ_ASSERT(aElement.IsHTMLElement());
nsAtom* tag = aElement.NodeInfo()->NameAtom();
NS_ASSERTION(!aParentFrame ||
aParentFrame->Style()->GetPseudoType() !=
PseudoStyleType::fieldsetContent ||
aParentFrame->GetParent()->IsFieldSetFrame(),
"Unexpected parent for fieldset content anon box");
if (tag == nsGkAtoms::legend &&
(!aParentFrame || !IsFrameForFieldSet(aParentFrame) ||
aStyle.StyleDisplay()->IsFloatingStyle() ||
aStyle.StyleDisplay()->IsAbsolutelyPositionedStyle())) {
// <legend> is only special inside fieldset, we only check the frame tree
// parent because the content tree parent may not be a <fieldset> due to
// display:contents, Shadow DOM, or XBL. For floated or absolutely
// positioned legends we want to construct by display type and
// not do special legend stuff.
return nullptr;
}
static const FrameConstructionDataByTag sHTMLData[] = {
SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData),
SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
@ -3433,9 +3420,6 @@ nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
COMPLEX_TAG_CREATE(fieldset,
&nsCSSFrameConstructor::ConstructFieldSetFrame),
{nsGkAtoms::legend,
FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME,
NS_NewLegendFrame)},
SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
{nsGkAtoms::button,
@ -3557,9 +3541,7 @@ nsCSSFrameConstructor::FindObjectData(const Element& aElement,
// cases when the object is broken/suppressed/etc (e.g. a broken image), but
// we want to treat those cases as TYPE_NULL
uint32_t type;
if (aElement.State().HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
NS_EVENT_STATE_USERDISABLED |
NS_EVENT_STATE_SUPPRESSED)) {
if (aElement.State().HasState(NS_EVENT_STATE_BROKEN)) {
type = nsIObjectLoadingContent::TYPE_NULL;
} else {
nsCOMPtr<nsIObjectLoadingContent> objContent =
@ -4028,26 +4010,6 @@ nsresult nsCSSFrameConstructor::GetAnonymousContent(
return NS_OK;
}
static bool IsXULDisplayType(const nsStyleDisplay* aDisplay) {
// -moz-{inline-}box is XUL, unless we're emulating it with flexbox.
if (!StaticPrefs::layout_css_emulate_moz_box_with_flex() &&
(aDisplay->mDisplay == StyleDisplay::MozInlineBox ||
aDisplay->mDisplay == StyleDisplay::MozBox)) {
return true;
}
#ifdef MOZ_XUL
return (aDisplay->mDisplay == StyleDisplay::MozGrid ||
aDisplay->mDisplay == StyleDisplay::MozStack ||
aDisplay->mDisplay == StyleDisplay::MozGridGroup ||
aDisplay->mDisplay == StyleDisplay::MozGridLine ||
aDisplay->mDisplay == StyleDisplay::MozDeck ||
aDisplay->mDisplay == StyleDisplay::MozPopup);
#else
return false;
#endif
}
// XUL frames are not allowed to be out of flow.
#define SIMPLE_XUL_FCDATA(_func) \
FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH, _func)
@ -4152,7 +4114,7 @@ nsCSSFrameConstructor::FindXULButtonData(const Element& aElement,
# ifdef MOZ_THUNDERBIRD
if (aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
NS_LITERAL_STRING("menu-button"), eCaseMatters)) {
u"menu-button"_ns, eCaseMatters)) {
return &sXULMenuData;
}
# endif
@ -4234,10 +4196,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::BeginBuildingScrollFrame(
if (!gfxScrollFrame) {
// Build a XULScrollFrame when the child is a box, otherwise an
// HTMLScrollFrame
// XXXbz this is the lone remaining consumer of IsXULDisplayType.
// I wonder whether we can eliminate that somehow.
const nsStyleDisplay* displayStyle = aContentStyle->StyleDisplay();
if (IsXULDisplayType(displayStyle)) {
if (displayStyle->IsXULDisplayStyle()) {
gfxScrollFrame = NS_NewXULScrollFrame(
mPresShell, contentStyle, aIsRoot,
displayStyle->mDisplay == StyleDisplay::MozStack);
@ -4351,7 +4311,7 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
// block-level.
NS_ASSERTION(
!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) ||
aDisplay.IsBlockOutsideStyle() || IsXULDisplayType(&aDisplay),
aDisplay.IsBlockOutsideStyle() || aDisplay.IsXULDisplayStyle(),
"Style system did not apply CSS2.1 section 9.7 fixups");
// If this is "body", try propagating its scroll style to the viewport
@ -4665,7 +4625,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructNonScrollableBlockWithConstructor(
if ((aDisplay->IsAbsolutelyPositionedStyle() || aDisplay->IsFloatingStyle() ||
aDisplay->DisplayInside() == StyleDisplayInside::FlowRoot ||
clipPaginatedOverflow) &&
!nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
!SVGUtils::IsInSVGTextSubtree(aParentFrame)) {
flags = NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS;
if (clipPaginatedOverflow) {
flags |= NS_BLOCK_CLIP_PAGINATED_OVERFLOW;
@ -4990,17 +4950,18 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
}
// We don't need frames for animation elements
if (aElement.IsNodeOfType(nsINode::eANIMATION)) {
if (nsCOMPtr<SVGAnimationElement> animationElement =
do_QueryInterface(const_cast<Element*>(&aElement))) {
return &sSuppressData;
}
if (tag == nsGkAtoms::svg && !parentIsSVG) {
// We need outer <svg> elements to have an nsSVGOuterSVGFrame regardless
// We need outer <svg> elements to have an SVGOuterSVGFrame regardless
// of whether they fail conditional processing attributes, since various
// SVG frames assume that one exists. We handle the non-rendering
// of failing outer <svg> element contents like <switch> statements,
// and do the PassesConditionalProcessingTests call in
// nsSVGOuterSVGFrame::Init.
// SVGOuterSVGFrame::Init.
static const FrameConstructionData sOuterSVGData =
FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructOuterSVG);
return &sOuterSVGData;
@ -5016,7 +4977,7 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
if (tests && !tests->PassesConditionalProcessingTests()) {
// Elements with failing conditional processing attributes never get
// rendered. Note that this is not where we select which frame in a
// <switch> to render! That happens in nsSVGSwitchFrame::PaintSVG.
// <switch> to render! That happens in SVGSwitchFrame::PaintSVG.
if (aIsWithinSVGText) {
// SVGTextFrame doesn't handle conditional processing attributes,
// so don't create frames for descendants of <text> with failing
@ -5024,7 +4985,7 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
// is correct.
return &sSuppressData;
}
// If we're not inside <text>, create an nsSVGContainerFrame (which is a
// If we're not inside <text>, create an SVGContainerFrame (which is a
// frame that doesn't render) so that paint servers can still be referenced,
// even if they live inside an element with failing conditional processing
// attributes.
@ -5033,9 +4994,8 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
// Ensure that a stop frame is a child of a gradient and that gradients
// can only have stop children.
bool parentIsGradient =
aParentFrame && (aParentFrame->IsSVGLinearGradientFrame() ||
aParentFrame->IsSVGRadialGradientFrame());
bool parentIsGradient = aParentFrame && static_cast<SVGGradientFrame*>(
do_QueryFrame(aParentFrame));
bool stop = (tag == nsGkAtoms::stop);
if ((parentIsGradient && !stop) || (!parentIsGradient && stop)) {
return &sSuppressData;
@ -5045,7 +5005,8 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
// primitives. If aParentFrame is null, we know that the frame that will
// be created will be an nsInlineFrame, so it can never be a filter.
bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
bool filterPrimitive = aElement.IsNodeOfType(nsINode::eFILTER);
nsCOMPtr<SVGFE> filterPrimitive =
do_QueryInterface(const_cast<Element*>(&aElement));
if ((parentIsFilter && !filterPrimitive) ||
(!parentIsFilter && filterPrimitive)) {
return &sSuppressData;
@ -5215,7 +5176,7 @@ void nsCSSFrameConstructor::DoAddFrameConstructionItems(
ItemFlags aFlags) {
auto flags = aFlags + ItemFlag::AllowPageBreak;
if (aParentFrame) {
if (nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
if (SVGUtils::IsInSVGTextSubtree(aParentFrame)) {
flags += ItemFlag::IsWithinSVGText;
}
if (aParentFrame->IsBlockFrame() && aParentFrame->GetParent() &&
@ -5250,10 +5211,18 @@ void nsCSSFrameConstructor::AddFrameConstructionItems(
static bool ShouldSuppressFrameInSelect(const nsIContent* aParent,
const nsIContent& aChild) {
if (!aParent ||
!aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup)) {
!aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup,
nsGkAtoms::option)) {
return false;
}
// Options with labels have their label text added in ::before by forms.css.
// Suppress frames for their child text.
if (aParent->IsHTMLElement(nsGkAtoms::option) &&
!aChild.IsRootOfAnonymousSubtree()) {
return aParent->AsElement()->HasNonEmptyAttr(nsGkAtoms::label);
}
// If we're in any display: contents subtree, just suppress the frame.
//
// We can't be regular NAC, since display: contents has no frame to generate
@ -5354,6 +5323,17 @@ nsCSSFrameConstructor::FindElementData(const Element& aElement,
return &sImgData;
}
if (aFlags.contains(ItemFlag::IsForRenderedLegend) &&
!aStyle.StyleDisplay()->IsBlockOutsideStyle()) {
// Make a temp copy of StyleDisplay and blockify its mDisplay value.
auto display = *aStyle.StyleDisplay();
bool isRootElement = false;
uint16_t rawDisplayValue =
Servo_ComputedValues_BlockifiedDisplay(&aStyle, isRootElement);
display.mDisplay = StyleDisplay(rawDisplayValue);
return FindDisplayData(display, aElement);
}
const auto& display = *aStyle.StyleDisplay();
return FindDisplayData(display, aElement);
}
@ -5518,6 +5498,16 @@ void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
return;
}
if (aContent->IsHTMLElement(nsGkAtoms::legend) && aParentFrame) {
const nsFieldSetFrame* fs = GetFieldSetFrameFor(aParentFrame);
if (fs && !fs->GetLegend() && !aState.mHasRenderedLegend &&
!aComputedStyle->StyleDisplay()->IsFloatingStyle() &&
!aComputedStyle->StyleDisplay()->IsAbsolutelyPositionedStyle()) {
aState.mHasRenderedLegend = true;
aFlags += ItemFlag::IsForRenderedLegend;
}
}
const FrameConstructionData* data =
FindDataForContent(*aContent, *aComputedStyle, aParentFrame, aFlags);
if (!data || data->mBits & FCDATA_SUPPRESS_FRAME) {
@ -5572,6 +5562,9 @@ void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
item = aItems.AppendItem(this, data, aContent, pendingBinding,
do_AddRef(aComputedStyle),
aSuppressWhiteSpaceOptimizations);
if (aFlags.contains(ItemFlag::IsForRenderedLegend)) {
item->mIsRenderedLegend = true;
}
}
item->mIsText = !aContent->IsElement();
item->mIsGeneratedContent = isGeneratedContent;
@ -6124,20 +6117,6 @@ bool nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
// below.
}
if (IsFrameForFieldSet(parentFrame)) {
// Legends can be sibling of legends but not of other content in the
// fieldset
if (nsContainerFrame* cif = aSibling->GetContentInsertionFrame()) {
aSibling = cif;
}
LayoutFrameType sibType = aSibling->Type();
bool legendContent = aContent->IsHTMLElement(nsGkAtoms::legend);
if ((legendContent && (LayoutFrameType::Legend != sibType)) ||
(!legendContent && (LayoutFrameType::Legend == sibType)))
return false;
}
return true;
}
@ -6225,6 +6204,10 @@ nsIFrame* nsCSSFrameConstructor::AdjustSiblingFrame(
return nullptr;
}
if (aSibling->IsRenderedLegend()) {
return nullptr;
}
if (aSibling->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
aSibling = aSibling->GetPlaceholderFrame();
MOZ_ASSERT(aSibling);
@ -7163,7 +7146,14 @@ void nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
// fieldsets have multiple insertion points.
NS_ASSERTION(isSingleInsert || frameType != LayoutFrameType::FieldSet,
"Unexpected parent");
if (IsFrameForFieldSet(insertion.mParentFrame) &&
// Note that this check is insufficient if aStartChild is not a legend with
// display::contents that contains a legend. We'll catch that case in
// WipeContainingBlock. (That code would also catch this case, but handling
// this early is slightly faster.)
// XXXmats we should be able to optimize this when the fieldset doesn't
// currently have a rendered legend. ContentRangeInserted needs to be fixed
// to use the inner frame as the content insertion frame in that case.
if (GetFieldSetFrameFor(insertion.mParentFrame) &&
aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
// Just reframe the parent, since figuring out whether this
// should be the new legend and then handling it is too complex.
@ -8090,8 +8080,10 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
"no support for fragmenting table captions yet");
newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
newFrame->Init(content, aParentFrame, aFrame);
} else if (LayoutFrameType::PrintedSheet == frameType) {
newFrame = ConstructPrintedSheetFrame(mPresShell, aParentFrame, aFrame);
} else if (LayoutFrameType::Page == frameType) {
nsContainerFrame* canvasFrame;
nsContainerFrame* canvasFrame; // (unused outparam for ConstructPageFrame)
newFrame =
ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
} else if (LayoutFrameType::TableWrapper == frameType) {
@ -8167,9 +8159,6 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
} else if (LayoutFrameType::FieldSet == frameType) {
newFrame = NS_NewFieldSetFrame(mPresShell, computedStyle);
newFrame->Init(content, aParentFrame, aFrame);
} else if (LayoutFrameType::Legend == frameType) {
newFrame = NS_NewLegendFrame(mPresShell, computedStyle);
newFrame->Init(content, aParentFrame, aFrame);
} else if (LayoutFrameType::FlexContainer == frameType) {
newFrame = NS_NewFlexContainerFrame(mPresShell, computedStyle);
newFrame->Init(content, aParentFrame, aFrame);
@ -8428,12 +8417,9 @@ bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
return true;
}
nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame();
if (insertionFrame && insertionFrame->IsLegendFrame() &&
aFrame->GetParent()->IsFieldSetFrame()) {
if (inFlowFrame->IsRenderedLegend()) {
TRACE("Fieldset / Legend");
RecreateFramesForContent(aFrame->GetParent()->GetContent(),
InsertionKind::Async);
RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
return true;
}
@ -9545,6 +9531,36 @@ inline void nsCSSFrameConstructor::ConstructFramesFromItemList(
// that information offhand in many cases.
MOZ_ASSERT(ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox);
// Note: we explicitly exclude TableColGroupFrame because it doesn't
// have the FCDATA_IS_WRAPPER_ANON_BOX on pseudos so aParentIsWrapperAnonBox
// is false for such pseudos (see sPseudoParentData below).
if (!aParentIsWrapperAnonBox && aState.mHasRenderedLegend &&
aParentFrame->GetContent()->IsHTMLElement(nsGkAtoms::fieldset) &&
!aParentFrame->IsTableColGroupFrame()) {
DebugOnly<bool> found = false;
for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
if (iter.item().mIsRenderedLegend) {
// This makes the rendered legend the first frame in the fieldset child
// list which makes keyboard traversal follow the visual order.
nsFieldSetFrame* fieldSetFrame = GetFieldSetFrameFor(aParentFrame);
nsFrameList renderedLegend;
ConstructFramesFromItem(aState, iter, fieldSetFrame, renderedLegend);
MOZ_ASSERT(
renderedLegend.FirstChild() &&
renderedLegend.FirstChild() == renderedLegend.LastChild(),
"a rendered legend should have exactly one frame");
fieldSetFrame->InsertFrames(kPrincipalList, nullptr, nullptr,
renderedLegend);
FCItemIterator next = iter;
next.Next();
iter.DeleteItemsTo(this, next);
found = true;
break;
}
}
MOZ_ASSERT(found, "should have found our rendered legend");
}
CreateNeededPseudoContainers(aState, aItems, aParentFrame);
CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
@ -9552,6 +9568,9 @@ inline void nsCSSFrameConstructor::ConstructFramesFromItemList(
bool listItemListIsDirty = false;
for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
MOZ_ASSERT(!iter.item().mIsRenderedLegend,
"Only one item can be the rendered legend, "
"and it should've been handled above");
NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
"Needed pseudos didn't get created; expect bad things");
// display:list-item boxes affects the start value of the "list-item"
@ -10136,7 +10155,7 @@ void nsCSSFrameConstructor::CreateLetterFrame(
const nsStyleDisplay* display = sc->StyleDisplay();
nsFirstLetterFrame* letterFrame;
if (display->IsFloatingStyle() &&
!nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
!SVGUtils::IsInSVGTextSubtree(aParentFrame)) {
// Make a floating first-letter frame
letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
aParentFrame, parentComputedStyle,
@ -11618,6 +11637,30 @@ bool nsCSSFrameConstructor::WipeContainingBlock(
// that is not part of an {ib} split, but should become an {ib} split.
}
// A <fieldset> may need to pick up a new rendered legend from aItems.
// We currently can't handle this case without recreating frames for
// the fieldset.
// XXXmats we should be able to optimize this when the fieldset doesn't
// currently have a rendered legend. ContentRangeInserted needs to be fixed
// to use the inner frame as the content insertion frame in that case.
if (const auto* fieldset = GetFieldSetFrameFor(aFrame)) {
// Check if any item is eligible to be a rendered legend.
for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
const auto& item = iter.item();
if (!item.mContent->IsHTMLElement(nsGkAtoms::legend)) {
continue;
}
const auto* display = item.mComputedStyle->StyleDisplay();
if (display->IsFloatingStyle() ||
display->IsAbsolutelyPositionedStyle()) {
continue;
}
TRACE("Fieldset with rendered legend");
RecreateFramesForContent(fieldset->GetContent(), InsertionKind::Async);
return true;
}
}
// Now we have several cases involving {ib} splits. Put them all in a
// do/while with breaks to take us to the "go and reconstruct" code.
do {

View File

@ -28,6 +28,7 @@
struct nsStyleDisplay;
struct nsGenConInitializer;
class nsBlockFrame;
class nsContainerFrame;
class nsFirstLineFrame;
class nsFirstLetterFrame;
@ -43,6 +44,7 @@ namespace mozilla {
class ComputedStyle;
class PresShell;
class PrintedSheetFrame;
namespace dom {
@ -365,6 +367,10 @@ class nsCSSFrameConstructor final : public nsFrameManager {
nsContainerFrame* aRootElementFrame, nsFrameConstructorState&,
nsFrameList&);
mozilla::PrintedSheetFrame* ConstructPrintedSheetFrame(
PresShell* aPresShell, nsContainerFrame* aParentFrame,
nsIFrame* aPrevSheetFrame);
nsContainerFrame* ConstructPageFrame(PresShell* aPresShell,
nsContainerFrame* aParentFrame,
nsIFrame* aPrevPageFrame,
@ -386,6 +392,8 @@ class nsCSSFrameConstructor final : public nsFrameManager {
AllowTextPathChild,
// The item is content created by an nsIAnonymousContentCreator frame.
IsAnonymousContentCreatorContent,
// The item will be the rendered legend of a <fieldset>.
IsForRenderedLegend,
};
using ItemFlags = mozilla::EnumSet<ItemFlag>;
@ -1118,7 +1126,8 @@ class nsCSSFrameConstructor final : public nsFrameManager {
mIsAllInline(false),
mIsBlock(false),
mIsPopup(false),
mIsLineParticipant(false) {
mIsLineParticipant(false),
mIsRenderedLegend(false) {
MOZ_COUNT_CTOR(FrameConstructionItem);
}
@ -1201,6 +1210,8 @@ class nsCSSFrameConstructor final : public nsFrameManager {
bool mIsPopup : 1;
// Whether this item should be treated as a line participant
bool mIsLineParticipant : 1;
// Whether this item is the rendered legend of a <fieldset>
bool mIsRenderedLegend : 1;
private:
// Not allocated from the general heap - instead, use the new/Delete APIs
@ -1516,7 +1527,7 @@ class nsCSSFrameConstructor final : public nsFrameManager {
mozilla::PseudoStyleType aInnerPseudo, bool aCandidateRootFrame);
/**
* Construct an nsSVGOuterSVGFrame.
* Construct an SVGOuterSVGFrame.
*/
nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
FrameConstructionItem& aItem,
@ -1525,7 +1536,7 @@ class nsCSSFrameConstructor final : public nsFrameManager {
nsFrameList& aFrameList);
/**
* Construct an nsSVGMarkerFrame.
* Construct an SVGMarkerFrame.
*/
nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
FrameConstructionItem& aItem,

View File

@ -333,13 +333,13 @@ nsRect nsCaret::GetGeometryForFrame(nsIFrame* aFrame, int32_t aFrameOffset,
// then snap it back, put it as close to the edge as it can.
if (vertical) {
nscoord overflow = caretInScroll.YMost() -
scrolled->GetVisualOverflowRectRelativeToSelf().height;
scrolled->InkOverflowRectRelativeToSelf().height;
if (overflow > 0) {
rect.y -= overflow;
}
} else {
nscoord overflow = caretInScroll.XMost() -
scrolled->GetVisualOverflowRectRelativeToSelf().width;
scrolled->InkOverflowRectRelativeToSelf().width;
if (overflow > 0) {
rect.x -= overflow;
}

View File

@ -9,10 +9,12 @@
#include "mozilla/Likely.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/PresShell.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/WritingModes.h"
#include "nsBulletFrame.h" // legacy location for list style type to text code
#include "nsContentUtils.h"
#include "nsIContent.h"
#include "nsContainerFrame.h"
#include "nsTArray.h"
#include "mozilla/dom/Text.h"
@ -126,6 +128,42 @@ void nsCounterList::SetScope(nsCounterNode* aNode) {
return;
}
// If there exist an explicit RESET scope created by an ancestor or
// the element itself, then we use that scope.
// Otherwise, fall through to consider scopes created by siblings (and
// their descendants) in reverse document order.
if (aNode->mType != nsCounterNode::USE &&
StaticPrefs::layout_css_counter_ancestor_scope_enabled()) {
for (auto* p = aNode->mPseudoFrame; p; p = p->GetParent()) {
// This relies on the fact that a RESET node is always the first
// CounterNode for a frame if it has any.
auto* counter = GetFirstNodeFor(p);
if (!counter || counter->mType != nsCounterNode::RESET) {
continue;
}
if (p == aNode->mPseudoFrame) {
break;
}
aNode->mScopeStart = counter;
aNode->mScopePrev = counter;
for (nsCounterNode* prev = Prev(aNode); prev;
prev = prev->mScopePrev) {
if (prev->mScopeStart == counter) {
aNode->mScopePrev =
prev->mType == nsCounterNode::RESET ? prev->mScopePrev : prev;
break;
}
if (prev->mType != nsCounterNode::RESET) {
prev = prev->mScopeStart;
if (!prev) {
break;
}
}
}
return;
}
}
// Get the content node for aNode's rendering object's *parent*,
// since scope includes siblings, so we want a descendant check on
// parents.
@ -155,6 +193,7 @@ void nsCounterList::SetScope(nsCounterNode* aNode) {
nodeContent == startContent) &&
// everything is inside the root (except the case above,
// a second reset on the root)
// FIXME(bug 1477524): should use flattened tree here:
(!startContent || nodeContent->IsInclusiveDescendantOf(startContent))) {
aNode->mScopeStart = start;
aNode->mScopePrev = prev;
@ -249,8 +288,10 @@ bool nsCounterManager::AddCounterChanges(nsIFrame* aFrame) {
int32_t i = 0;
for (const auto& pair : styleContent->mCounterIncrement.AsSpan()) {
hasListItemIncrement |= pair.name.AsAtom() == nsGkAtoms::list_item;
dirty |= AddCounterChangeNode(*this, aFrame, i++, pair,
nsCounterChangeNode::INCREMENT);
if (pair.value != 0) {
dirty |= AddCounterChangeNode(*this, aFrame, i++, pair,
nsCounterChangeNode::INCREMENT);
}
}
}
@ -320,7 +361,7 @@ void nsCounterManager::Dump() {
nsCounterList* list = iter.UserData();
int32_t i = 0;
for (nsCounterNode* node = list->First(); node; node = list->Next(node)) {
const char* types[] = {"RESET", "SET", "INCREMENT", "USE"};
const char* types[] = {"RESET", "INCREMENT", "SET", "USE"};
printf(
" Node #%d @%p frame=%p index=%d type=%s valAfter=%d\n"
" scope-start=%p scope-prev=%p",

View File

@ -170,6 +170,11 @@ class nsCounterList : public nsGenConList {
public:
nsCounterList() : nsGenConList(), mDirty(false) {}
// Return the first node for aFrame on this list, or nullptr.
nsCounterNode* GetFirstNodeFor(nsIFrame* aFrame) const {
return static_cast<nsCounterNode*>(nsGenConList::GetFirstNodeFor(aFrame));
}
void Insert(nsCounterNode* aNode) {
nsGenConList::Insert(aNode);
// Don't SetScope if we're dirty -- we'll reset all the scopes anyway,

View File

@ -17,6 +17,7 @@
#include "nsIContent.h"
#include "nsIContentViewer.h"
#include "nsIDocumentViewerPrint.h"
#include "nsIScreen.h"
#include "mozilla/dom/BeforeUnloadEvent.h"
#include "mozilla/dom/PopupBlocker.h"
#include "mozilla/dom/Document.h"
@ -142,9 +143,6 @@ static mozilla::LazyLogModule gPrintingLog("printing");
//-----------------------------------------------------
class nsDocumentViewer;
namespace mozilla {
class AutoPrintEventDispatcher;
}
// a small delegate class used to avoid circular references
@ -462,7 +460,6 @@ class nsDocumentViewer final : public nsIContentViewer,
RefPtr<nsPrintJob> mPrintJob;
float mOriginalPrintPreviewScale;
float mPrintPreviewZoom;
UniquePtr<AutoPrintEventDispatcher> mAutoBeforeAndAfterPrint;
# endif // NS_PRINT_PREVIEW
#endif // NS_PRINTING
@ -470,59 +467,12 @@ class nsDocumentViewer final : public nsIContentViewer,
/* character set member data */
int32_t mHintCharsetSource;
const Encoding* mHintCharset;
const Encoding* mForceCharacterSet;
bool mIsPageMode;
bool mInitializedForPrintPreview;
bool mHidden;
};
namespace mozilla {
/**
* A RAII class for automatic dispatch of the 'beforeprint' and 'afterprint'
* events ('beforeprint' on construction, 'afterprint' on destruction).
*
* https://developer.mozilla.org/en-US/docs/Web/Events/beforeprint
* https://developer.mozilla.org/en-US/docs/Web/Events/afterprint
*/
class AutoPrintEventDispatcher {
public:
explicit AutoPrintEventDispatcher(Document* aTop) : mTop(aTop) {
DispatchEventToWindowTree(NS_LITERAL_STRING("beforeprint"));
}
~AutoPrintEventDispatcher() {
DispatchEventToWindowTree(NS_LITERAL_STRING("afterprint"));
}
private:
static bool CollectDocuments(Document& aDoc,
nsTArray<nsCOMPtr<Document>>& aDocs) {
aDocs.AppendElement(&aDoc);
auto recurse = [&aDocs](Document& aSubDoc) {
return CollectDocuments(aSubDoc, aDocs);
};
aDoc.EnumerateSubDocuments(recurse);
return true;
}
void DispatchEventToWindowTree(const nsAString& aEvent) {
nsTArray<nsCOMPtr<Document>> targets;
if (mTop) {
CollectDocuments(*mTop, targets);
}
for (nsCOMPtr<Document>& doc : targets) {
nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent,
CanBubble::eNo, Cancelable::eNo,
nullptr);
}
}
nsCOMPtr<Document> mTop;
};
} // namespace mozilla
class nsDocumentShownDispatcher : public Runnable {
public:
explicit nsDocumentShownDispatcher(nsCOMPtr<Document> aDocument)
@ -593,7 +543,6 @@ nsDocumentViewer::nsDocumentViewer()
#endif // NS_PRINTING
mHintCharsetSource(kCharsetUninitialized),
mHintCharset(nullptr),
mForceCharacterSet(nullptr),
mIsPageMode(false),
mInitializedForPrintPreview(false),
mHidden(false) {
@ -668,10 +617,8 @@ void nsDocumentViewer::RemoveFocusListener() {
std::move(mFocusListener)) {
oldListener->Disconnect();
if (mDocument) {
mDocument->RemoveEventListener(NS_LITERAL_STRING("focus"), oldListener,
false);
mDocument->RemoveEventListener(NS_LITERAL_STRING("blur"), oldListener,
false);
mDocument->RemoveEventListener(u"focus"_ns, oldListener, false);
mDocument->RemoveEventListener(u"blur"_ns, oldListener, false);
}
}
}
@ -680,10 +627,8 @@ void nsDocumentViewer::ReinitializeFocusListener() {
RemoveFocusListener();
mFocusListener = new nsDocViewerFocusListener(this);
if (mDocument) {
mDocument->AddEventListener(NS_LITERAL_STRING("focus"), mFocusListener,
false, false);
mDocument->AddEventListener(NS_LITERAL_STRING("blur"), mFocusListener,
false, false);
mDocument->AddEventListener(u"focus"_ns, mFocusListener, false, false);
mDocument->AddEventListener(u"blur"_ns, mFocusListener, false, false);
}
}
@ -1268,7 +1213,7 @@ nsresult nsDocumentViewer::PermitUnloadInternal(uint32_t* aPermitUnloadFlags,
nsPresContext* presContext = mDocument->GetPresContext();
RefPtr<BeforeUnloadEvent> event =
new BeforeUnloadEvent(mDocument, presContext, nullptr);
event->InitEvent(NS_LITERAL_STRING("beforeunload"), false, true);
event->InitEvent(u"beforeunload"_ns, false, true);
// Dispatching to |window|, but using |document| as the target.
event->SetTarget(mDocument);
@ -1621,14 +1566,6 @@ nsDocumentViewer::Close(nsISHEntry* aSHEntry) {
mDocument->AddMutationObserver(mBFCachePreventionObserver);
}
#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
// Turn scripting back on
// after PrintPreview had turned it off
if (GetIsPrintPreview() && mPrintJob) {
mPrintJob->TurnScriptingOn(true);
}
#endif
#ifdef NS_PRINTING
// A Close was called while we were printing
// so don't clear the ScriptGlobalObject
@ -1698,8 +1635,6 @@ nsDocumentViewer::Destroy() {
return NS_OK;
}
}
// Dispatch the 'afterprint' event now, if pending:
mAutoBeforeAndAfterPrint = nullptr;
#endif
// We want to make sure to disconnect mBFCachePreventionObserver before we
@ -2702,8 +2637,8 @@ nsDocumentViewer::SetTextZoom(float aTextZoom) {
// Dispatch TextZoomChange event only if text zoom value has changed.
if (textZoomChange) {
nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
NS_LITERAL_STRING("TextZoomChange"),
CanBubble::eYes, Cancelable::eYes);
u"TextZoomChange"_ns, CanBubble::eYes,
Cancelable::eYes);
}
return NS_OK;
@ -2717,14 +2652,6 @@ nsDocumentViewer::GetTextZoom(float* aTextZoom) {
return NS_OK;
}
NS_IMETHODIMP
nsDocumentViewer::GetEffectiveTextZoom(float* aEffectiveTextZoom) {
NS_ENSURE_ARG_POINTER(aEffectiveTextZoom);
nsPresContext* pc = GetPresContext();
*aEffectiveTextZoom = pc ? pc->EffectiveTextZoom() : 1.0f;
return NS_OK;
}
NS_IMETHODIMP
nsDocumentViewer::SetFullZoom(float aFullZoom) {
#ifdef NS_PRINT_PREVIEW
@ -2735,7 +2662,7 @@ nsDocumentViewer::SetFullZoom(float aFullZoom) {
NS_ENSURE_TRUE(presShell, NS_OK);
if (!mPrintPreviewZoomed) {
mOriginalPrintPreviewScale = pc->GetPrintPreviewScale();
mOriginalPrintPreviewScale = pc->GetPrintPreviewScaleForSequenceFrame();
mPrintPreviewZoomed = true;
}
@ -2774,8 +2701,8 @@ nsDocumentViewer::SetFullZoom(float aFullZoom) {
// Dispatch FullZoomChange event only if fullzoom value really has changed.
if (fullZoomChange) {
nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
NS_LITERAL_STRING("FullZoomChange"),
CanBubble::eYes, Cancelable::eYes);
u"FullZoomChange"_ns, CanBubble::eYes,
Cancelable::eYes);
}
return NS_OK;
@ -2798,18 +2725,8 @@ nsDocumentViewer::GetFullZoom(float* aFullZoom) {
}
NS_IMETHODIMP
nsDocumentViewer::GetDeviceFullZoom(float* aDeviceFullZoom) {
nsDocumentViewer::GetDeviceFullZoomForTest(float* aDeviceFullZoom) {
NS_ENSURE_ARG_POINTER(aDeviceFullZoom);
#ifdef NS_PRINT_PREVIEW
if (GetIsPrintPreview()) {
// Print Preview overrides all zoom; if specified, we use the print preview
// zoom, no matter what.
*aDeviceFullZoom = mPrintPreviewZoom;
return NS_OK;
}
#endif
// If not in print preview, ask the prescontext for the device zoom, if a
// prescontext is available.
nsPresContext* pc = GetPresContext();
*aDeviceFullZoom = pc ? pc->GetDeviceFullZoom() : mPageZoom;
return NS_OK;
@ -2891,46 +2808,6 @@ nsDocumentViewer::StopEmulatingMedium() {
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::GetForceCharacterSet(
nsACString& aForceCharacterSet) {
auto encoding = nsDocumentViewer::GetForceCharset();
if (encoding) {
encoding->Name(aForceCharacterSet);
} else {
aForceCharacterSet.Truncate();
}
return NS_OK;
}
/* [noscript,notxpcom] Encoding getForceCharset (); */
NS_IMETHODIMP_(const Encoding*)
nsDocumentViewer::GetForceCharset() { return mForceCharacterSet; }
NS_IMETHODIMP
nsDocumentViewer::SetForceCharacterSet(const nsACString& aForceCharacterSet) {
// The empty string means no hint.
const Encoding* encoding = nullptr;
if (!aForceCharacterSet.IsEmpty()) {
if (!(encoding = Encoding::ForLabel(aForceCharacterSet))) {
// Reject unknown labels
return NS_ERROR_INVALID_ARG;
}
}
nsDocumentViewer::SetForceCharset(encoding);
return NS_OK;
}
/* [noscript,notxpcom] void setForceCharset (in Encoding aEncoding); */
NS_IMETHODIMP_(void)
nsDocumentViewer::SetForceCharset(const Encoding* aEncoding) {
mForceCharacterSet = aEncoding;
auto childFn = [aEncoding](nsDocumentViewer* aChild) {
aChild->SetForceCharset(aEncoding);
};
// now set the force char set on all children of mContainer
CallChildren(childFn);
}
NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSet(
nsACString& aHintCharacterSet) {
auto encoding = nsDocumentViewer::GetHintCharset();
@ -3279,7 +3156,7 @@ NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(
// might need another update string for simple selection changes, but that
// would be expenseive.
if (mSelectionWasCollapsed != selectionCollapsed) {
domWindow->UpdateCommands(NS_LITERAL_STRING("select"), selection, aReason);
domWindow->UpdateCommands(u"select"_ns, selection, aReason);
mSelectionWasCollapsed = selectionCollapsed;
}
@ -3379,41 +3256,20 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
return NS_ERROR_FAILURE;
}
nsresult rv;
// if we are printing another URL, then exit
// the reason we check here is because this method can be called while
// another is still in here (the printing dialog is a good example).
// the only time we can print more than one job at a time is the regression
// tests
if (GetIsPrinting()) {
// Let the user know we are not ready to print.
rv = NS_ERROR_NOT_AVAILABLE;
if (mPrintJob) {
mPrintJob->FirePrintingErrorEvent(rv);
}
return rv;
}
// Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
MOZ_ASSERT(!mAutoBeforeAndAfterPrint,
"We don't want to dispatch nested beforeprint/afterprint");
auto autoBeforeAndAfterPrint =
MakeUnique<AutoPrintEventDispatcher>(mDocument);
NS_ENSURE_STATE(!GetIsPrinting());
// If we are hosting a full-page plugin, tell it to print
// first. It shows its own native print UI.
nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(mDocument));
if (pDoc) return pDoc->Print();
if (pDoc) {
return pDoc->Print();
}
nsresult rv;
// Our call to nsPrintJob::Print() may cause mPrintJob to be
// Release()'d in Destroy(). Therefore, we need to grab the instance with
// a local variable, so that it won't be deleted during its own method.
RefPtr<nsPrintJob> printJob = mPrintJob;
if (!printJob) {
NS_ENSURE_STATE(mDeviceContext);
printJob = new nsPrintJob();
rv = printJob->Initialize(this, mContainer, mDocument,
@ -3425,12 +3281,17 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
return rv;
}
mPrintJob = printJob;
} else if (printJob->GetIsPrinting()) {
// if we are printing another URL, then exit
// the reason we check here is because this method can be called while
// another is still in here (the printing dialog is a good example).
// the only time we can print more than one job at a time is the regression
// tests
rv = NS_ERROR_NOT_AVAILABLE;
printJob->FirePrintingErrorEvent(rv);
return rv;
}
if (printJob->HasPrintCallbackCanvas()) {
// Postpone the 'afterprint' event until after the mozPrintCallback
// callbacks have been called:
mAutoBeforeAndAfterPrint = std::move(autoBeforeAndAfterPrint);
}
rv = printJob->Print(mDocument, aPrintSettings, aWebProgressListener);
if (NS_FAILED(rv)) {
OnDonePrinting();
@ -3472,18 +3333,6 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
nsCOMPtr<Document> doc = window->GetDoc();
NS_ENSURE_STATE(doc);
// Dispatch 'beforeprint' event and ensure 'afterprint' will be dispatched:
// XXX Currently[1] when the user switches between portrait and landscape
// mode in print preview, we re-enter this function before
// mAutoBeforeAndAfterPrint (if set) is cleared to dispatch the 'afterprint'
// event. To avoid sending multiple 'beforeprint'/'afterprint' events we
// must avoid creating a new AutoPrintEventDispatcher object here if we
// already have one saved in mAutoBeforeAndAfterPrint.
// [1] Until PDF.js is removed (though, maybe after that as well).
UniquePtr<AutoPrintEventDispatcher> autoBeforeAndAfterPrint;
if (!mAutoBeforeAndAfterPrint) {
autoBeforeAndAfterPrint = MakeUnique<AutoPrintEventDispatcher>(doc);
}
NS_ENSURE_STATE(!GetIsPrinting());
// beforeprint event may have caused ContentViewer to be shutdown.
NS_ENSURE_STATE(mContainer);
@ -3506,11 +3355,6 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
}
mPrintJob = printJob;
}
if (autoBeforeAndAfterPrint && printJob->HasPrintCallbackCanvas()) {
// Postpone the 'afterprint' event until after the mozPrintCallback
// callbacks have been called:
mAutoBeforeAndAfterPrint = std::move(autoBeforeAndAfterPrint);
}
rv = printJob->PrintPreview(doc, aPrintSettings, aWebProgressListener);
mPrintPreviewZoomed = false;
if (NS_FAILED(rv)) {
@ -3541,14 +3385,13 @@ nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
}
// in PP mPrtPreview->mPrintObject->mSeqFrame is null
nsIFrame* seqFrame = nullptr;
int32_t pageCount = 0;
if (NS_FAILED(mPrintJob->GetSeqFrameAndCountPages(seqFrame, pageCount))) {
auto [seqFrame, pageCount] = mPrintJob->GetSeqFrameAndCountPages();
if (!seqFrame) {
return NS_ERROR_FAILURE;
}
// Figure where we are currently scrolled to
nsPoint pt = sf->GetScrollPosition();
nsPoint currentScrollPosition = sf->GetScrollPosition();
int32_t pageNum = 1;
nsIFrame* fndPageFrame = nullptr;
@ -3562,13 +3405,13 @@ nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
// Now, locate the current page we are on and
// and the page of the page number
for (nsIFrame* pageFrame : seqFrame->PrincipalChildList()) {
nsRect pageRect = pageFrame->GetRect();
if (pageRect.Contains(pageRect.x, pt.y)) {
currentPage = pageFrame;
for (nsIFrame* sheetFrame : seqFrame->PrincipalChildList()) {
nsRect sheetRect = sheetFrame->GetRect();
if (sheetRect.Contains(sheetRect.x, currentScrollPosition.y)) {
currentPage = sheetFrame;
}
if (pageNum == aPageNum) {
fndPageFrame = pageFrame;
fndPageFrame = sheetFrame;
break;
}
pageNum++;
@ -3599,9 +3442,10 @@ nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
}
if (fndPageFrame) {
nscoord newYPosn = nscoord(mPrintJob->GetPrintPreviewScale() *
nscoord newYPosn = nscoord(seqFrame->GetPrintPreviewScale() *
fndPageFrame->GetPosition().y);
sf->ScrollTo(nsPoint(pt.x, newYPosn), ScrollMode::Instant);
sf->ScrollTo(nsPoint(currentScrollPosition.x, newYPosn),
ScrollMode::Instant);
}
return NS_OK;
}
@ -3687,7 +3531,6 @@ nsDocumentViewer::ExitPrintPreview() {
}
# ifdef NS_PRINT_PREVIEW
mPrintJob->TurnScriptingOn(true);
mPrintJob->Destroy();
mPrintJob = nullptr;
@ -3718,24 +3561,6 @@ nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) {
return *aPrintPreviewNumPages > 0 ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDocumentViewer::GetIsIFrameSelected(bool* aIsIFrameSelected) {
*aIsIFrameSelected = false;
NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
*aIsIFrameSelected = mPrintJob->IsIFrameSelected();
return NS_OK;
}
NS_IMETHODIMP
nsDocumentViewer::GetIsRangeSelection(bool* aIsRangeSelection) {
*aIsRangeSelection = false;
NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
*aIsRangeSelection = mPrintJob->IsRangeSelection();
return NS_OK;
}
//----------------------------------------------------------------------------------
// Printing/Print Preview Helpers
//----------------------------------------------------------------------------------
@ -3814,7 +3639,7 @@ bool nsDocumentViewer::ShouldAttachToTopLevel() {
//------------------------------------------------------------
// XXX this always returns false for subdocuments
bool nsDocumentViewer::GetIsPrinting() {
bool nsDocumentViewer::GetIsPrinting() const {
#ifdef NS_PRINTING
if (mPrintJob) {
return mPrintJob->GetIsPrinting();
@ -3835,11 +3660,6 @@ void nsDocumentViewer::SetIsPrinting(bool aIsPrinting) {
} else {
NS_WARNING("Did you close a window before printing?");
}
if (!aIsPrinting) {
// Dispatch the 'afterprint' event now, if pending:
mAutoBeforeAndAfterPrint = nullptr;
}
#endif
}
@ -3847,7 +3667,7 @@ void nsDocumentViewer::SetIsPrinting(bool aIsPrinting) {
// The PrintJob holds the current value
// this called from inside the DocViewer.
// XXX it always returns false for subdocuments
bool nsDocumentViewer::GetIsPrintPreview() {
bool nsDocumentViewer::GetIsPrintPreview() const {
#ifdef NS_PRINTING
if (mPrintJob) {
return mPrintJob->GetIsPrintPreview();
@ -3866,10 +3686,6 @@ void nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview) {
if (docShell || !aIsPrintPreview) {
SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true);
}
if (!aIsPrintPreview) {
// Dispatch the 'afterprint' event now, if pending:
mAutoBeforeAndAfterPrint = nullptr;
}
#endif
// Protect against pres shell destruction running scripts.

View File

@ -8,12 +8,12 @@
#define nsGenConList_h___
#include "mozilla/LinkedList.h"
#include "nsIFrame.h"
#include "nsStyleStruct.h"
#include "nsCSSPseudoElements.h"
#include "nsTextNode.h"
class nsGenConList;
class nsIFrame;
struct nsGenConNode : public mozilla::LinkedListElement<nsGenConNode> {
using StyleContentType = mozilla::StyleContentItem::Tag;
@ -110,6 +110,11 @@ class nsGenConList {
// have been destroyed; otherwise false.
bool DestroyNodesFor(nsIFrame* aFrame);
// Return the first node for aFrame on this list, or nullptr.
nsGenConNode* GetFirstNodeFor(nsIFrame* aFrame) const {
return mNodes.Get(aFrame);
}
// Return true if |aNode1| is after |aNode2|.
static bool NodeAfter(const nsGenConNode* aNode1, const nsGenConNode* aNode2);

View File

@ -32,10 +32,10 @@ class nsIDocumentViewerPrint : public nsISupports {
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_VIEWER_PRINT_IID)
virtual void SetIsPrinting(bool aIsPrinting) = 0;
virtual bool GetIsPrinting() = 0;
virtual bool GetIsPrinting() const = 0;
virtual void SetIsPrintPreview(bool aIsPrintPreview) = 0;
virtual bool GetIsPrintPreview() = 0;
virtual bool GetIsPrintPreview() const = 0;
/**
* This is used by nsPagePrintTimer to make nsDocumentViewer::Destroy()
@ -71,9 +71,9 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint,
/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_NSIDOCUMENTVIEWERPRINT \
void SetIsPrinting(bool aIsPrinting) override; \
bool GetIsPrinting() override; \
bool GetIsPrinting() const override; \
void SetIsPrintPreview(bool aIsPrintPreview) override; \
bool GetIsPrintPreview() override; \
bool GetIsPrintPreview() const override; \
void IncrementDestroyBlockedCount() override; \
void DecrementDestroyBlockedCount() override; \
void OnDonePrinting() override; \

View File

@ -5,7 +5,8 @@
#define NSIFRAMETRAVERSAL_H
#include "nsISupports.h"
#include "nsIFrame.h"
class nsIFrame;
#define NS_IFRAMEENUMERATOR_IID \
{ \

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,9 @@
#include "mozilla/LookAndFeel.h"
#include "mozilla/Maybe.h"
#include "mozilla/ReflowOutput.h"
#include "mozilla/RelativeTo.h"
#include "mozilla/StaticPrefs_nglayout.h"
#include "mozilla/SurfaceFromElementResult.h"
#include "mozilla/SVGImageContext.h"
#include "mozilla/ToString.h"
#include "mozilla/TypedEnumBits.h"
@ -56,11 +58,11 @@ class nsIFrame;
class nsPIDOMWindowOuter;
class imgIRequest;
struct nsStyleFont;
struct nsOverflowAreas;
namespace mozilla {
struct AspectRatio;
class ComputedStyle;
class DisplayPortUtils;
class PresShell;
enum class PseudoStyleType : uint8_t;
class EventListenerManager;
@ -71,7 +73,9 @@ class WritingMode;
class DisplayItemClip;
class EffectSet;
struct ActiveScrolledRoot;
enum class ScrollOrigin : uint8_t;
enum class StyleImageOrientation : uint8_t;
struct OverflowAreas;
namespace dom {
class CanvasRenderingContext2D;
class DOMRectList;
@ -100,31 +104,6 @@ class Layer;
} // namespace layers
} // namespace mozilla
namespace mozilla {
struct DisplayPortPropertyData {
DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority,
bool aPainted)
: mRect(aRect), mPriority(aPriority), mPainted(aPainted) {}
nsRect mRect;
uint32_t mPriority;
bool mPainted;
};
struct DisplayPortMarginsPropertyData {
DisplayPortMarginsPropertyData(const ScreenMargin& aMargins,
uint32_t aPriority, bool aPainted)
: mMargins(aMargins), mPriority(aPriority), mPainted(aPainted) {}
ScreenMargin mMargins;
uint32_t mPriority;
bool mPainted;
};
} // namespace mozilla
// For GetDisplayPort
enum class RelativeTo { ScrollPort, ScrollFrame };
// Flags to customize the behavior of nsLayoutUtils::DrawString.
enum class DrawStringFlags {
Default = 0x0,
@ -132,6 +111,17 @@ enum class DrawStringFlags {
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DrawStringFlags)
enum class ScrollableDirection { Horizontal, Vertical, Either };
namespace mozilla {
class RectCallback {
public:
virtual void AddRect(const nsRect& aRect) = 0;
};
} // namespace mozilla
/**
* nsLayoutUtils is a namespace class used for various helper
* functions that are useful in multiple places in layout. The goal
@ -149,6 +139,9 @@ class nsLayoutUtils {
#endif
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
typedef mozilla::IntrinsicSize IntrinsicSize;
typedef mozilla::RelativeTo RelativeTo;
typedef mozilla::ScrollOrigin ScrollOrigin;
typedef mozilla::ViewportType ViewportType;
typedef mozilla::gfx::SourceSurface SourceSurface;
typedef mozilla::gfx::Color Color;
typedef mozilla::gfx::DrawTarget DrawTarget;
@ -208,134 +201,17 @@ class nsLayoutUtils {
*/
static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId);
/**
* Helper for FindScrollableFrameFor(), also used in DisplayPortUtils.
* Most clients should use FindScrollableFrameFor().
*/
static nsIFrame* GetScrollFrameFromContent(nsIContent* aContent);
/**
* Find the ID for a given scrollable frame.
*/
static ViewID FindIDForScrollableFrame(nsIScrollableFrame* aScrollable);
/**
* Get display port for the given element, relative to the specified entity,
* defaulting to the scrollport.
*/
static bool GetDisplayPort(nsIContent* aContent, nsRect* aResult,
RelativeTo aRelativeTo = RelativeTo::ScrollPort,
bool* aOutPainted = nullptr);
/**
* Check whether the given element has a displayport.
*/
static bool HasDisplayPort(nsIContent* aContent);
/**
* 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);
/**
* 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.
*/
static bool FrameHasDisplayPort(nsIFrame* aFrame,
const nsIFrame* aScrolledFrame = nullptr);
/**
* 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);
/**
* 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();
/**
* @return the display port for the given element which should be used for
* visibility testing purposes.
*
* If low-precision buffers are enabled, this is the critical display port;
* otherwise, it's the same display port returned by GetDisplayPort().
*/
static bool GetDisplayPortForVisibilityTesting(
nsIContent* aContent, nsRect* aResult,
RelativeTo aRelativeTo = RelativeTo::ScrollPort);
enum class RepaintMode : uint8_t { Repaint, DoNotRepaint };
/**
* Invalidate for displayport change.
*/
static void InvalidateForDisplayPortChange(
nsIContent* aContent, bool aHadDisplayPort, const nsRect& aOldDisplayPort,
const nsRect& aNewDisplayPort,
RepaintMode aRepaintMode = RepaintMode::Repaint);
/**
* 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
* @return true if the new margins were applied.
*/
static bool SetDisplayPortMargins(
nsIContent* aContent, PresShell* aPresShell, const ScreenMargin& aMargins,
uint32_t aPriority = 0, RepaintMode aRepaintMode = RepaintMode::Repaint);
/**
* Set the display port base rect for given element to be used with display
* port margins.
* SetDisplayPortBaseIfNotSet is like SetDisplayPortBase except it only sets
* the display port base to aBase if no display port base is currently set.
*/
static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase);
static void SetDisplayPortBaseIfNotSet(nsIContent* aContent,
const nsRect& aBase);
/**
* Get the critical display port for the given element.
*/
static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult,
bool* aOutPainted = nullptr);
/**
* Check whether the given element has a critical display port.
*/
static bool HasCriticalDisplayPort(nsIContent* aContent);
/**
* If low-precision painting is turned on, delegates to
* GetCriticalDisplayPort. Otherwise, delegates to GetDisplayPort.
*/
static bool GetHighResolutionDisplayPort(nsIContent* aContent,
nsRect* aResult,
bool* aOutPainted = nullptr);
/**
* Remove the displayport for the given element.
*/
static void RemoveDisplayPort(nsIContent* aContent);
/**
* 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.
@ -586,8 +462,8 @@ class nsLayoutUtils {
* aFrame == aAncestorFrame.
*/
static bool IsProperAncestorFrameCrossDoc(
nsIFrame* aAncestorFrame, nsIFrame* aFrame,
nsIFrame* aCommonAncestor = nullptr);
const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
const nsIFrame* aCommonAncestor = nullptr);
/**
* IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor
@ -631,19 +507,6 @@ class nsLayoutUtils {
*/
static ViewID ScrollIdForRootScrollFrame(nsPresContext* aPresContext);
/**
* Return true if aPresContext's viewport has a displayport.
*/
static bool ViewportHasDisplayPort(nsPresContext* aPresContext);
/**
* Return true if aFrame is a fixed-pos frame and is a child of a viewport
* 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).
*/
static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame);
/**
* GetScrollableFrameFor returns the scrollable frame for a scrolled frame
*/
@ -662,9 +525,8 @@ class nsLayoutUtils {
* @param aDirection Whether it's for horizontal or vertical scrolling.
* @return the nearest scrollable frame or nullptr if not found
*/
enum Direction { eHorizontal, eVertical };
static nsIScrollableFrame* GetNearestScrollableFrameForDirection(
nsIFrame* aFrame, Direction aDirection);
nsIFrame* aFrame, ScrollableDirection aDirection);
enum {
/**
@ -770,7 +632,7 @@ class nsLayoutUtils {
* the event is not a GUI event).
*/
static nsPoint GetEventCoordinatesRelativeTo(
const mozilla::WidgetEvent* aEvent, nsIFrame* aFrame);
const mozilla::WidgetEvent* aEvent, RelativeTo aFrame);
/**
* Get the coordinates of a given point relative to an event and a
@ -784,7 +646,7 @@ class nsLayoutUtils {
*/
static nsPoint GetEventCoordinatesRelativeTo(
const mozilla::WidgetEvent* aEvent,
const mozilla::LayoutDeviceIntPoint& aPoint, nsIFrame* aFrame);
const mozilla::LayoutDeviceIntPoint& aPoint, RelativeTo aFrame);
/**
* Get the coordinates of a given point relative to a widget and a
@ -798,7 +660,7 @@ class nsLayoutUtils {
*/
static nsPoint GetEventCoordinatesRelativeTo(
nsIWidget* aWidget, const mozilla::LayoutDeviceIntPoint& aPoint,
nsIFrame* aFrame);
RelativeTo aFrame);
/**
* Get the popup frame of a given native mouse event.
@ -844,12 +706,13 @@ class nsLayoutUtils {
* @param aPresContext the PresContext for the view
* @param aView the view
* @param aPt the point relative to the view
* @param aViewportType whether the point is in visual or layout coordinates
* @param aWidget the widget to which returned coordinates are relative
* @return the point in the view's coordinates
*/
static mozilla::LayoutDeviceIntPoint TranslateViewToWidget(
nsPresContext* aPresContext, nsView* aView, nsPoint aPt,
nsIWidget* aWidget);
ViewportType aViewportType, nsIWidget* aWidget);
static mozilla::LayoutDeviceIntPoint WidgetToWidgetOffset(
nsIWidget* aFromWidget, nsIWidget* aToWidget);
@ -879,21 +742,23 @@ class nsLayoutUtils {
* Given aFrame, the root frame of a stacking context, find its descendant
* frame under the point aPt that receives a mouse event at that location,
* or nullptr if there is no such frame.
* @param aPt the point, relative to the frame origin
* @param aPt the point, relative to the frame origin, in either visual
* or layout coordinates depending on aRelativeTo.mViewportType
* @param aFlags some combination of FrameForPointOption.
*/
static nsIFrame* GetFrameForPoint(const nsIFrame* aFrame, nsPoint aPt,
static nsIFrame* GetFrameForPoint(RelativeTo aRelativeTo, nsPoint aPt,
mozilla::EnumSet<FrameForPointOption> = {});
/**
* Given aFrame, the root frame of a stacking context, find all descendant
* frames under the area of a rectangle that receives a mouse event,
* or nullptr if there is no such frame.
* @param aRect the rect, relative to the frame origin
* @param aRect the rect, relative to the frame origin, in either visual
* or layout coordinates depending on aRelativeTo.mViewportType
* @param aOutFrames an array to add all the frames found
* @param aFlags some combination of FrameForPointOption.
*/
static nsresult GetFramesForArea(const nsIFrame* aFrame, const nsRect& aRect,
static nsresult GetFramesForArea(RelativeTo aRelativeTo, const nsRect& aRect,
nsTArray<nsIFrame*>& aOutFrames,
mozilla::EnumSet<FrameForPointOption> = {});
@ -902,6 +767,8 @@ class nsLayoutUtils {
* aAncestor. Computes the bounding-box of the true quadrilateral.
* Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if
* we only need to use a 2d transform that PreservesAxisAlignedRectangles().
* The corner positions of aRect are treated as meaningful even if aRect is
* empty.
*
* |aMatrixCache| allows for optimizations in recomputing the same matrix over
* and over. The argument can be one of the following values:
@ -922,6 +789,17 @@ class nsLayoutUtils {
bool* aPreservesAxisAlignedRectangles = nullptr,
mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false,
nsIFrame** aOutAncestor = nullptr) {
return TransformFrameRectToAncestor(
aFrame, aRect, RelativeTo{aAncestor}, aPreservesAxisAlignedRectangles,
aMatrixCache, aStopAtStackingContextAndDisplayPortAndOOFFrame,
aOutAncestor);
}
static nsRect TransformFrameRectToAncestor(
const nsIFrame* aFrame, const nsRect& aRect, RelativeTo aAncestor,
bool* aPreservesAxisAlignedRectangles = nullptr,
mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false,
nsIFrame** aOutAncestor = nullptr);
/**
@ -930,9 +808,41 @@ class nsLayoutUtils {
* flag in aFlags will return CSS pixels, by default it returns device
* pixels.
* More info can be found in nsIFrame::GetTransformMatrix.
*
* Some notes on the possible combinations of |aFrame.mViewportType| and
* |aAncestor.mViewportType|:
*
* | aFrame. | aAncestor. | Notes
* | mViewportType | mViewportType |
* ==========================================================================
* | Layout | Layout | Commonplace, when both source and target
* | | | are inside zoom boundary.
* | | |
* | | | Could also happen in non-e10s setups
* | | | when both source and target are outside
* | | | the zoom boundary and the code is
* | | | oblivious to the existence of a zoom
* | | | boundary.
* ==========================================================================
* | Layout | Visual | Commonplace, used when hit testing visual
* | | | coordinates (e.g. coming from user input
* | | | events). We expected to encounter a
* | | | zoomed content root during traversal and
* | | | apply a layout-to-visual transform.
* ==========================================================================
* | Visual | Layout | Should never happen, will assert.
* ==========================================================================
* | Visual | Visual | In e10s setups, should only happen if
* | | | aFrame and aAncestor are both the
* | | | RCD viewport frame.
* | | |
* | | | In non-e10s setups, could happen with
* | | | different frames if they are both
* | | | outside the zoom boundary.
* ==========================================================================
*/
static Matrix4x4Flagged GetTransformToAncestor(
const nsIFrame* aFrame, const nsIFrame* aAncestor, uint32_t aFlags = 0,
RelativeTo aFrame, RelativeTo aAncestor, uint32_t aFlags = 0,
nsIFrame** aOutAncestor = nullptr);
/**
@ -953,8 +863,17 @@ class nsLayoutUtils {
* Find the nearest common ancestor frame for aFrame1 and aFrame2. The
* ancestor frame could be cross-doc.
*/
static nsIFrame* FindNearestCommonAncestorFrame(nsIFrame* aFrame1,
nsIFrame* aFrame2);
static const nsIFrame* FindNearestCommonAncestorFrame(
const nsIFrame* aFrame1, const nsIFrame* aFrame2);
/**
* Find the nearest common ancestor frame for aFrame1 and aFrame2, assuming
* that they are within the same block.
*
* Returns null if they are not within the same block.
*/
static const nsIFrame* FindNearestCommonAncestorFrameWithinBlock(
const nsTextFrame* aFrame1, const nsTextFrame* aFrame2);
/**
* Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into
@ -980,16 +899,16 @@ class nsLayoutUtils {
* Same as above function, but transform points in app units and
* handle 1 point per call.
*/
static TransformResult TransformPoint(nsIFrame* aFromFrame,
nsIFrame* aToFrame, nsPoint& aPoint);
static TransformResult TransformPoint(RelativeTo aFromFrame,
RelativeTo aToFrame, nsPoint& aPoint);
/**
* Transforms a rect from aFromFrame to aToFrame. In app units.
* Returns the bounds of the actual rect if the transform requires rotation
* or anything complex like that.
*/
static TransformResult TransformRect(nsIFrame* aFromFrame, nsIFrame* aToFrame,
nsRect& aRect);
static TransformResult TransformRect(const nsIFrame* aFromFrame,
const nsIFrame* aToFrame, nsRect& aRect);
/**
* Converts app units to pixels (with optional snapping) and appends as a
@ -1039,23 +958,27 @@ class nsLayoutUtils {
* in the coordinate system of aFrame. This effectively inverts all
* transforms between this point and the root frame.
*
* @param aFromType Specifies whether |aPoint| is in layout or visual
* coordinates.
* @param aFrame The frame that acts as the coordinate space container.
* @param aPoint The point, in the global space, to get in the frame-local
* space.
* @param aPoint The point, in global layout or visual coordinates (as per
* |aFromType|, to get in the frame-local space.
* @return aPoint, expressed in aFrame's canonical coordinate space.
*/
static nsPoint TransformRootPointToFrame(nsIFrame* aFrame,
static nsPoint TransformRootPointToFrame(ViewportType aFromType,
RelativeTo aFrame,
const nsPoint& aPoint) {
return TransformAncestorPointToFrame(aFrame, aPoint, nullptr);
return TransformAncestorPointToFrame(aFrame, aPoint,
RelativeTo{nullptr, aFromType});
}
/**
* Transform aPoint relative to aAncestor down to the coordinate system of
* aFrame.
*/
static nsPoint TransformAncestorPointToFrame(nsIFrame* aFrame,
static nsPoint TransformAncestorPointToFrame(RelativeTo aFrame,
const nsPoint& aPoint,
nsIFrame* aAncestor);
RelativeTo aAncestor);
/**
* Helper function that, given a rectangle and a matrix, returns the smallest
@ -1116,9 +1039,6 @@ class nsLayoutUtils {
const nscoord aRadii[8],
const nsRect& aTestRect);
static bool MaybeCreateDisplayPortInFirstScrollFrameEncountered(
nsIFrame* aFrame, nsDisplayListBuilder* aBuilder);
enum class PaintFrameFlags : uint32_t {
InTransform = 0x01,
SyncDecodeImages = 0x02,
@ -1234,12 +1154,7 @@ class nsLayoutUtils {
*/
static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame);
class RectCallback {
public:
virtual void AddRect(const nsRect& aRect) = 0;
};
struct RectAccumulator : public RectCallback {
struct RectAccumulator : public mozilla::RectCallback {
nsRect mResultRect;
nsRect mFirstRect;
bool mSeenFirstRect;
@ -1249,7 +1164,7 @@ class nsLayoutUtils {
virtual void AddRect(const nsRect& aRect) override;
};
struct RectListBuilder : public RectCallback {
struct RectListBuilder : public mozilla::RectCallback {
DOMRectList* mRectList;
explicit RectListBuilder(DOMRectList* aList);
@ -1283,10 +1198,12 @@ class nsLayoutUtils {
* Otherwise (by default), the border box is used.
*/
static void GetAllInFlowRects(nsIFrame* aFrame, const nsIFrame* aRelativeTo,
RectCallback* aCallback, uint32_t aFlags = 0);
mozilla::RectCallback* aCallback,
uint32_t aFlags = 0);
static void GetAllInFlowRectsAndTexts(
nsIFrame* aFrame, const nsIFrame* aRelativeTo, RectCallback* aCallback,
nsIFrame* aFrame, const nsIFrame* aRelativeTo,
mozilla::RectCallback* aCallback,
mozilla::dom::Sequence<nsString>* aTextList, uint32_t aFlags = 0);
/**
@ -1478,9 +1395,6 @@ class nsLayoutUtils {
* size by reducing the *content size* (flooring at zero). This is used for:
* https://drafts.csswg.org/css-grid/#min-size-auto
*/
enum class IntrinsicISizeType { MinISize, PrefISize };
static const auto MIN_ISIZE = IntrinsicISizeType::MinISize;
static const auto PREF_ISIZE = IntrinsicISizeType::PrefISize;
enum {
IGNORE_PADDING = 0x01,
BAIL_IF_REFLOW_NEEDED = 0x02, // returns NS_INTRINSIC_ISIZE_UNKNOWN if so
@ -1488,7 +1402,7 @@ class nsLayoutUtils {
};
static nscoord IntrinsicForAxis(
mozilla::PhysicalAxis aAxis, gfxContext* aRenderingContext,
nsIFrame* aFrame, IntrinsicISizeType aType,
nsIFrame* aFrame, mozilla::IntrinsicISizeType aType,
const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(),
uint32_t aFlags = 0, nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE);
/**
@ -1496,7 +1410,7 @@ class nsLayoutUtils {
*/
static nscoord IntrinsicForContainer(gfxContext* aRenderingContext,
nsIFrame* aFrame,
IntrinsicISizeType aType,
mozilla::IntrinsicISizeType aType,
uint32_t aFlags = 0);
/**
@ -1520,7 +1434,7 @@ class nsLayoutUtils {
*/
static nscoord MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis,
gfxContext* aRC, nsIFrame* aFrame,
IntrinsicISizeType aType,
mozilla::IntrinsicISizeType aType,
const LogicalSize& aPercentageBasis,
uint32_t aFlags = 0);
@ -2150,87 +2064,21 @@ class nsLayoutUtils {
SFE_USE_ELEMENT_SIZE_IF_VECTOR = 1 << 5
};
struct DirectDrawInfo {
/* imgIContainer to directly draw to a context */
nsCOMPtr<imgIContainer> mImgContainer;
/* which frame to draw */
uint32_t mWhichFrame;
/* imgIContainer flags to use when drawing */
uint32_t mDrawingFlags;
};
struct SurfaceFromElementResult {
friend class mozilla::dom::CanvasRenderingContext2D;
friend class nsLayoutUtils;
/* If SFEResult contains a valid surface, it either mLayersImage or
* mSourceSurface will be non-null, and GetSourceSurface() will not be null.
*
* For valid surfaces, mSourceSurface may be null if mLayersImage is
* non-null, but GetSourceSurface() will create mSourceSurface from
* mLayersImage when called.
*/
/* Video elements (at least) often are already decoded as layers::Images. */
RefPtr<mozilla::layers::Image> mLayersImage;
protected:
/* GetSourceSurface() fills this and returns its non-null value if this
* SFEResult was successful. */
RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
public:
/* Contains info for drawing when there is no mSourceSurface. */
DirectDrawInfo mDrawInfo;
/* The size of the surface */
mozilla::gfx::IntSize mSize;
/* The size the surface is intended to be rendered at */
mozilla::gfx::IntSize mIntrinsicSize;
/* The principal associated with the element whose surface was returned.
If there is a surface, this will never be null. */
nsCOMPtr<nsIPrincipal> mPrincipal;
/* The image request, if the element is an nsIImageLoadingContent */
nsCOMPtr<imgIRequest> mImageRequest;
/* True if cross-origins redirects have been done in order to load this
* resource */
bool mHadCrossOriginRedirects;
/* Whether the element was "write only", that is, the bits should not be
* exposed to content */
bool mIsWriteOnly;
/* Whether the element was still loading. Some consumers need to handle
this case specially. */
bool mIsStillLoading;
/* Whether the element has a valid size. */
bool mHasSize;
/* Whether the element used CORS when loading. */
bool mCORSUsed;
gfxAlphaType mAlphaType;
// Methods:
SurfaceFromElementResult();
// Gets mSourceSurface, or makes a SourceSurface from mLayersImage.
const RefPtr<mozilla::gfx::SourceSurface>& GetSourceSurface();
};
// This function can be called on any thread.
static SurfaceFromElementResult SurfaceFromOffscreenCanvas(
static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas(
mozilla::dom::OffscreenCanvas* aOffscreenCanvas, uint32_t aSurfaceFlags,
RefPtr<DrawTarget>& aTarget);
static SurfaceFromElementResult SurfaceFromOffscreenCanvas(
static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas(
mozilla::dom::OffscreenCanvas* aOffscreenCanvas,
uint32_t aSurfaceFlags = 0) {
RefPtr<DrawTarget> target = nullptr;
return SurfaceFromOffscreenCanvas(aOffscreenCanvas, aSurfaceFlags, target);
}
static SurfaceFromElementResult SurfaceFromElement(
static mozilla::SurfaceFromElementResult SurfaceFromElement(
mozilla::dom::Element* aElement, uint32_t aSurfaceFlags,
RefPtr<DrawTarget>& aTarget);
static SurfaceFromElementResult SurfaceFromElement(
static mozilla::SurfaceFromElementResult SurfaceFromElement(
mozilla::dom::Element* aElement, uint32_t aSurfaceFlags = 0) {
RefPtr<DrawTarget> target = nullptr;
return SurfaceFromElement(aElement, aSurfaceFlags, target);
@ -2238,19 +2086,19 @@ class nsLayoutUtils {
// There are a bunch of callers of SurfaceFromElement. Just mark it as
MOZ_CAN_RUN_SCRIPT_BOUNDARY
static SurfaceFromElementResult SurfaceFromElement(
static mozilla::SurfaceFromElementResult SurfaceFromElement(
nsIImageLoadingContent* aElement, uint32_t aSurfaceFlags,
RefPtr<DrawTarget>& aTarget);
// Need an HTMLImageElement overload, because otherwise the
// nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous
// for HTMLImageElement.
static SurfaceFromElementResult SurfaceFromElement(
static mozilla::SurfaceFromElementResult SurfaceFromElement(
mozilla::dom::HTMLImageElement* aElement, uint32_t aSurfaceFlags,
RefPtr<DrawTarget>& aTarget);
static SurfaceFromElementResult SurfaceFromElement(
static mozilla::SurfaceFromElementResult SurfaceFromElement(
mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags,
RefPtr<DrawTarget>& aTarget);
static SurfaceFromElementResult SurfaceFromElement(
static mozilla::SurfaceFromElementResult SurfaceFromElement(
mozilla::dom::HTMLVideoElement* aElement, uint32_t aSurfaceFlags,
RefPtr<DrawTarget>& aTarget);
@ -2443,7 +2291,7 @@ class nsLayoutUtils {
* kSelectPopupList and kPopupList are always skipped.
*/
static void UnionChildOverflow(
nsIFrame* aFrame, nsOverflowAreas& aOverflowAreas,
nsIFrame* aFrame, mozilla::OverflowAreas& aOverflowAreas,
mozilla::layout::FrameChildListIDs aSkipChildLists =
mozilla::layout::FrameChildListIDs());
@ -2624,12 +2472,12 @@ class nsLayoutUtils {
*/
enum class SubtractDynamicToolbar { No, Yes };
static bool GetContentViewerSize(
nsPresContext* aPresContext, LayoutDeviceIntSize& aOutSize,
const nsPresContext* aPresContext, LayoutDeviceIntSize& aOutSize,
SubtractDynamicToolbar = SubtractDynamicToolbar::Yes);
private:
static bool UpdateCompositionBoundsForRCDRSF(
mozilla::ParentLayerRect& aCompBounds, nsPresContext* aPresContext);
mozilla::ParentLayerRect& aCompBounds, const nsPresContext* aPresContext);
public:
/**
@ -2657,7 +2505,7 @@ class nsLayoutUtils {
* mDevPixelsPerCSSPixel set.
*/
static CSSSize CalculateRootCompositionSize(
nsIFrame* aFrame, bool aIsRootContentDocRootScrollFrame,
const nsIFrame* aFrame, bool aIsRootContentDocRootScrollFrame,
const FrameMetrics& aMetrics);
/**
@ -2667,7 +2515,7 @@ class nsLayoutUtils {
* scrollable rect as the rect of the root frame.
*/
static nsRect CalculateScrollableRectForFrame(
nsIScrollableFrame* aScrollableFrame, nsIFrame* aRootFrame);
const nsIScrollableFrame* aScrollableFrame, const nsIFrame* aRootFrame);
/**
* Calculate the expanded scrollable rect for a frame. See FrameMetrics.h for
@ -2764,47 +2612,8 @@ class nsLayoutUtils {
static FrameMetrics CalculateBasicFrameMetrics(
nsIScrollableFrame* aScrollFrame);
/**
* Calculate a default set of displayport margins for the given scrollframe
* and set them on the scrollframe's content element. The margins are set with
* the default priority, which may clobber previously set margins. The repaint
* mode provided is passed through to the call to SetDisplayPortMargins.
* The |aScrollFrame| parameter must be non-null and queryable to an nsIFrame.
* @return true iff the call to SetDisplayPortMargins returned true.
*/
static bool CalculateAndSetDisplayPortMargins(
nsIScrollableFrame* aScrollFrame, RepaintMode aRepaintMode);
/**
* If |aScrollFrame| WantsAsyncScroll() and we don't have a scrollable
* displayport yet (as tracked by |aBuilder|), calculate and set a
* displayport.
*
* If this is called during display list building pass DoNotRepaint in
* aRepaintMode.
*
* Returns true if there is a displayport on an async scrollable scrollframe
* after this call, either because one was just added or it already existed.
*/
static bool MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
nsIFrame* aScrollFrame,
RepaintMode aRepaintMode);
static nsIScrollableFrame* GetAsyncScrollableAncestorFrame(nsIFrame* aTarget);
/**
* Sets a zero margin display port on all proper ancestors of aFrame that
* are async scrollable.
*/
static void SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
nsIFrame* aFrame);
/**
* Finds the closest ancestor async scrollable frame from aFrame that has a
* displayport and attempts to trigger the displayport expiry on that
* ancestor.
*/
static void ExpireDisplayPortOnAsyncScrollableAncestor(nsIFrame* aFrame);
static void SetBSizeFromFontMetrics(
const nsIFrame* aFrame, mozilla::ReflowOutput& aMetrics,
const mozilla::LogicalMargin& aFramePadding, mozilla::WritingMode aLineWM,
@ -2826,13 +2635,13 @@ class nsLayoutUtils {
* returns true for those, and returns false for other origins like APZ
* itself, or scroll position updates from the history restore code.
*/
static bool CanScrollOriginClobberApz(nsAtom* aScrollOrigin);
static bool CanScrollOriginClobberApz(ScrollOrigin aScrollOrigin);
static ScrollMetadata ComputeScrollMetadata(
nsIFrame* aForFrame, nsIFrame* aScrollFrame, nsIContent* aContent,
const nsIFrame* aReferenceFrame,
nsIFrame* aForFrame, nsIFrame* aScrollFrame,
nsIContent* aContent, const nsIFrame* aReferenceFrame,
mozilla::layers::LayerManager* aLayerManager, ViewID aScrollParentId,
const nsRect& aViewport, const mozilla::Maybe<nsRect>& aClipRect,
const nsSize& aScrollPortSize, const mozilla::Maybe<nsRect>& aClipRect,
bool aIsRoot,
const mozilla::Maybe<ContainerLayerParameters>& aContainerParameters);
@ -2859,7 +2668,7 @@ class nsLayoutUtils {
* scrollable content.
*/
static nsMargin ScrollbarAreaToExcludeFromCompositionBoundsFor(
nsIFrame* aScrollFrame);
const nsIFrame* aScrollFrame);
/**
* Looks in the layer subtree rooted at aLayer for a metrics with scroll id
@ -2979,11 +2788,6 @@ class nsLayoutUtils {
static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame);
// Return the default value to be used for -moz-control-character-visibility,
// from preferences.
static mozilla::StyleControlCharacterVisibility
ControlCharVisibilityDefault();
// Callers are responsible to ensure the user-font-set is up-to-date if
// aUseUserFontSet is true.
static already_AddRefed<nsFontMetrics> GetMetricsFor(

View File

@ -495,7 +495,7 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) {
mMissingFonts = nullptr;
}
}
if (StringBeginsWith(prefName, NS_LITERAL_CSTRING("font.")) ||
if (StringBeginsWith(prefName, "font."_ns) ||
prefName.EqualsLiteral("intl.accept_languages")) {
// Changes to font family preferences don't change anything in the
// computed style data, so the style system won't generate a reflow
@ -507,14 +507,14 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) {
// bother (yet, anyway).
mPrefChangePendingNeedsReflow = true;
}
if (StringBeginsWith(prefName, NS_LITERAL_CSTRING("bidi."))) {
if (StringBeginsWith(prefName, "bidi."_ns)) {
// Changes to bidi prefs need to trigger a reflow (see bug 443629)
mPrefChangePendingNeedsReflow = true;
// Changes to bidi.numeral also needs to empty the text run cache.
// This is handled in gfxTextRunWordCache.cpp.
}
if (StringBeginsWith(prefName, NS_LITERAL_CSTRING("gfx.font_rendering."))) {
if (StringBeginsWith(prefName, "gfx.font_rendering."_ns)) {
// Changes to font_rendering prefs need to trigger a reflow
mPrefChangePendingNeedsReflow = true;
}
@ -803,7 +803,7 @@ nsPresContext* nsPresContext::GetParentPresContext() {
return nullptr;
}
nsPresContext* nsPresContext::GetToplevelContentDocumentPresContext() {
nsPresContext* nsPresContext::GetInProcessRootContentDocumentPresContext() {
if (IsChrome()) return nullptr;
nsPresContext* pc = this;
for (;;) {
@ -1191,7 +1191,7 @@ void nsPresContext::RecordInteractionTime(InteractionType aType,
// Record the interaction time if it occurs after the first paint
// of the top level content document.
nsPresContext* topContentPresContext =
GetToplevelContentDocumentPresContext();
GetInProcessRootContentDocumentPresContext();
if (!topContentPresContext) {
// There is no top content pres context so we don't care
@ -1259,11 +1259,6 @@ void nsPresContext::ThemeChanged() {
}
}
static bool NotifyThemeChanged(BrowserParent* aBrowserParent, void* aArg) {
aBrowserParent->ThemeChanged();
return false;
}
void nsPresContext::ThemeChangedInternal() {
mPendingThemeChanged = false;
@ -1291,8 +1286,11 @@ void nsPresContext::ThemeChangedInternal() {
// Recursively notify all remote leaf descendants that the
// system theme has changed.
if (nsPIDOMWindowOuter* window = mDocument->GetWindow()) {
nsContentUtils::CallOnAllRemoteChildren(window, NotifyThemeChanged,
nullptr);
nsContentUtils::CallOnAllRemoteChildren(
window, [](BrowserParent* aBrowserParent) -> bool {
aBrowserParent->ThemeChanged();
return false;
});
}
}
@ -1506,10 +1504,6 @@ void nsPresContext::FlushPendingMediaFeatureValuesChanged() {
RebuildAllStyleData(change.mChangeHint, change.mRestyleHint);
}
if (!mPresShell || !mPresShell->DidInitialize()) {
return;
}
if (mDocument->IsBeingUsedAsImage()) {
MOZ_ASSERT(mDocument->MediaQueryLists().isEmpty());
return;
@ -1517,12 +1511,15 @@ void nsPresContext::FlushPendingMediaFeatureValuesChanged() {
mDocument->NotifyMediaFeatureValuesChanged();
MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsSafeToRunScript());
// https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes
//
// Media query list listeners should be notified from a queued task
// (in HTML5 terms), although we also want to notify them on certain
// flushes. (We're already running off an event.)
//
// TODO: This should be better integrated into the "update the rendering"
// steps: https://html.spec.whatwg.org/#update-the-rendering
//
// Note that we do this after the new style from media queries in
// style sheets has been computed.
@ -1532,32 +1529,31 @@ void nsPresContext::FlushPendingMediaFeatureValuesChanged() {
// We build a list of all the notifications we're going to send
// before we send any of them.
// Copy pointers to all the lists into a new array, in case one of our
// notifications modifies the list.
nsTArray<RefPtr<mozilla::dom::MediaQueryList>> localMediaQueryLists;
nsTArray<RefPtr<mozilla::dom::MediaQueryList>> listsToNotify;
for (MediaQueryList* mql = mDocument->MediaQueryLists().getFirst(); mql;
mql = static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext()) {
localMediaQueryLists.AppendElement(mql);
if (mql->MediaFeatureValuesChanged()) {
listsToNotify.AppendElement(mql);
}
}
// Now iterate our local array of the lists.
for (const auto& mql : localMediaQueryLists) {
nsAutoMicroTask mt;
mql->MaybeNotify();
}
}
static bool NotifyTabSizeModeChanged(BrowserParent* aTab, void* aArg) {
nsSizeMode* sizeMode = static_cast<nsSizeMode*>(aArg);
aTab->SizeModeChanged(*sizeMode);
return false;
nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
"nsPresContext::FlushPendingMediaFeatureValuesChanged",
[list = std::move(listsToNotify)] {
for (const auto& mql : list) {
nsAutoMicroTask mt;
mql->FireChangeEvent();
}
}));
}
void nsPresContext::SizeModeChanged(nsSizeMode aSizeMode) {
if (nsPIDOMWindowOuter* window = mDocument->GetWindow()) {
nsContentUtils::CallOnAllRemoteChildren(window, NotifyTabSizeModeChanged,
&aSizeMode);
nsContentUtils::CallOnAllRemoteChildren(
window, [&aSizeMode](BrowserParent* aBrowserParent) -> bool {
aBrowserParent->SizeModeChanged(aSizeMode);
return false;
});
}
MediaFeatureValuesChangedAllDocuments(
{MediaFeatureChangeReason::SizeModeChange});
@ -1573,7 +1569,24 @@ void nsPresContext::SetPaginatedScrolling(bool aPaginated) {
}
void nsPresContext::SetPrintSettings(nsIPrintSettings* aPrintSettings) {
if (mMedium == nsGkAtoms::print) mPrintSettings = aPrintSettings;
if (mMedium != nsGkAtoms::print) {
return;
}
mPrintSettings = aPrintSettings;
mDefaultPageMargin = nsMargin();
if (!mPrintSettings) {
return;
}
nsIntMargin unwriteableTwips = mPrintSettings->GetUnwriteableMarginInTwips();
NS_ASSERTION(unwriteableTwips.top >= 0 && unwriteableTwips.right >= 0 &&
unwriteableTwips.bottom >= 0 && unwriteableTwips.left >= 0,
"Unwriteable twips should be non-negative");
nsIntMargin marginTwips = mPrintSettings->GetMarginInTwips();
marginTwips.EnsureAtLeast(unwriteableTwips);
mDefaultPageMargin = nsPresContext::CSSTwipsToAppUnits(marginTwips);
}
bool nsPresContext::EnsureVisible() {
@ -2442,7 +2455,7 @@ void nsRootPresContext::ComputePluginGeometryUpdates(
// again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
// again.
aBuilder->SetAllowMergingAndFlattening(false);
nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
nsRegion region = rootFrame->InkOverflowRectRelativeToSelf();
// nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
// widget configuration for the plugin, if it's visible.
aList->ComputeVisibilityForRoot(aBuilder, &region);

View File

@ -179,10 +179,10 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
nsPresContext* GetParentPresContext();
/**
* Returns the prescontext of the toplevel content document that contains
* this presentation, or null if there isn't one.
* Returns the prescontext of the root content document in the same process
* that contains this presentation, or null if there isn't one.
*/
nsPresContext* GetToplevelContentDocumentPresContext();
nsPresContext* GetInProcessRootContentDocumentPresContext();
/**
* Returns the nearest widget for the root frame or view of this.
@ -398,7 +398,8 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
/**
* Get/set the size of a page
*/
nsSize GetPageSize() { return mPageSize; }
const nsSize& GetPageSize() const { return mPageSize; }
const nsMargin& GetDefaultPageMargin() const { return mDefaultPageMargin; }
void SetPageSize(nsSize aSize) { mPageSize = aSize; }
/**
@ -421,14 +422,19 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
void SetPageScale(float aScale) { mPageScale = aScale; }
/**
* Get/set the scaling facor to use when rendering the pages for print
* Get/set the scaling factor to use when rendering the pages for print
* preview. Only safe to get after print preview set up; safe to set anytime.
* This is a scaling factor for the display of the print preview. It
* does not affect layout. It only affects the size of the onscreen pages
* in print preview.
*
* The getter should only be used by the page sequence frame, which is the
* frame responsible for applying the scaling. Other callers should use
* nsPageSequenceFrame::GetPrintPreviewScale() if needed, instead of this API.
*
* XXX Temporary: see http://wiki.mozilla.org/Gecko:PrintPreview
*/
float GetPrintPreviewScale() { return mPPScale; }
float GetPrintPreviewScaleForSequenceFrame() { return mPPScale; }
void SetPrintPreviewScale(float aScale) { mPPScale = aScale; }
nsDeviceContext* DeviceContext() const { return mDeviceContext; }
@ -1132,6 +1138,16 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
nsRect mVisibleArea;
nsSize mPageSize;
// The computed page margins from the print settings.
//
// This margin will be used for each page in the current print operation, by
// default (i.e. unless overridden by @page rules).
//
// FIXME(emilio): Maybe we could let a global @page rule do that, though it's
// sketchy at best, see https://github.com/w3c/csswg-drafts/issues/5437 for
// discussion.
nsMargin mDefaultPageMargin;
float mPageScale;
float mPPScale;

View File

@ -31,6 +31,7 @@
#include "mozilla/AutoRestore.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/DisplayPortUtils.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/FontTableURIProtocolHandler.h"
@ -1867,7 +1868,7 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime) {
// in the queue. This will prevent us from spending precious time
// painting a stale displayport.
if (StaticPrefs::apz_peek_messages_enabled()) {
nsLayoutUtils::UpdateDisplayPortMarginsFromPendingMessages();
DisplayPortUtils::UpdateDisplayPortMarginsFromPendingMessages();
}
AutoTArray<nsCOMPtr<nsIRunnable>, 16> earlyRunners = std::move(mEarlyRunners);

View File

@ -20,16 +20,15 @@
#include "nsTHashtable.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsRefreshObservers.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/dom/VisualViewport.h"
#include "mozilla/layers/TransactionIdAllocator.h"
#include "mozilla/VsyncDispatcher.h"
class nsPresContext;
class imgIRequest;
class nsINode;
class nsIRunnable;
namespace mozilla {
@ -43,51 +42,8 @@ namespace layout {
class VsyncChild;
} // namespace layout
namespace dom {
class Event;
} // namespace dom
} // namespace mozilla
/**
* An abstract base class to be implemented by callers wanting to be
* notified at refresh times. When nothing needs to be painted, callers
* may not be notified.
*/
class nsARefreshObserver {
public:
// AddRef and Release signatures that match nsISupports. Implementors
// must implement reference counting, and those that do implement
// nsISupports will already have methods with the correct signature.
//
// The refresh driver does NOT hold references to refresh observers
// except while it is notifying them.
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
MOZ_CAN_RUN_SCRIPT virtual void WillRefresh(mozilla::TimeStamp aTime) = 0;
};
/**
* An abstract base class to be implemented by callers wanting to be notified
* when the observing refresh driver updated mMostRecentRefresh due to active
* timer changes. Callers must ensure an observer is removed before it is
* destroyed.
*/
class nsATimerAdjustmentObserver {
public:
virtual void NotifyTimerAdjusted(mozilla::TimeStamp aTime) = 0;
};
/**
* An abstract base class to be implemented by callers wanting to be notified
* that a refresh has occurred. Callers must ensure an observer is removed
* before it is destroyed.
*/
class nsAPostRefreshObserver {
public:
virtual void DidRefresh() = 0;
};
class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
public nsARefreshObserver {
using Document = mozilla::dom::Document;
@ -427,7 +383,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
EnsureTimerStarted();
}
void IntersectionObservationAdded() {
void EnsureIntersectionObservationsUpdateHappens() {
// This is enough to make sure that UpdateIntersectionObservations runs at
// least once. This is presumably the intent of step 5 in [1]:
//

View File

@ -0,0 +1,65 @@
/* 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/. */
/*
* Code to notify things that animate before a refresh, at an appropriate
* refresh rate. (Perhaps temporary, until replaced by compositor.)
*/
#ifndef LAYOUT_BASE_NSREFRESHOBSERVERS_H_
#define LAYOUT_BASE_NSREFRESHOBSERVERS_H_
#include "mozilla/Attributes.h"
#include "mozilla/TimeStamp.h"
#include "nsISupports.h"
namespace mozilla {
class AnimationEventDispatcher;
class PendingFullscreenEvent;
class RefreshDriverTimer;
namespace layout {
class VsyncChild;
}
} // namespace mozilla
/**
* An abstract base class to be implemented by callers wanting to be
* notified at refresh times. When nothing needs to be painted, callers
* may not be notified.
*/
class nsARefreshObserver {
public:
// AddRef and Release signatures that match nsISupports. Implementors
// must implement reference counting, and those that do implement
// nsISupports will already have methods with the correct signature.
//
// The refresh driver does NOT hold references to refresh observers
// except while it is notifying them.
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
MOZ_CAN_RUN_SCRIPT virtual void WillRefresh(mozilla::TimeStamp aTime) = 0;
};
/**
* An abstract base class to be implemented by callers wanting to be notified
* when the observing refresh driver updated mMostRecentRefresh due to active
* timer changes. Callers must ensure an observer is removed before it is
* destroyed.
*/
class nsATimerAdjustmentObserver {
public:
virtual void NotifyTimerAdjusted(mozilla::TimeStamp aTime) = 0;
};
/**
* An abstract base class to be implemented by callers wanting to be notified
* that a refresh has occurred. Callers must ensure an observer is removed
* before it is destroyed.
*/
class nsAPostRefreshObserver {
public:
virtual void DidRefresh() = 0;
};
#endif

View File

@ -10,10 +10,7 @@
</style>
<div contenteditable="true" spellcheck="false">
xx
<span contenteditable="false">
NOT EDITABLE
</span>
xxx
<span contenteditable="false">NOT EDITABLE</span>xxx
</div>
<script>
SimpleTest.waitForFocus(function() {

View File

@ -0,0 +1,27 @@
<!doctype html>
<html class="reftest-wait">
<title>Select non-editable content in an editor</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
div:focus {
outline: 3px solid blue;
}
</style>
<div contenteditable="true" spellcheck="false">
xx<span contenteditable="false">NOT EDITABLE</span>xxx
</div>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('[contenteditable="true"]').focus();
requestAnimationFrame(function() {
// Move after the two x
for (let i = 0; i < 2; ++i) {
synthesizeKey("KEY_ArrowRight");
}
// Select <span>
synthesizeKey("KEY_ArrowRight", { shiftKey: true });
document.documentElement.removeAttribute("class");
});
});
</script>

View File

@ -0,0 +1,27 @@
<!doctype html>
<html class="reftest-wait">
<title>Select non-editable content in an editor</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
div:focus {
outline: 3px solid blue;
}
</style>
<div contenteditable="true" spellcheck="false">
xx<span contenteditable="false">NOT EDITABLE</span>xxx
</div>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('[contenteditable="true"]').focus();
requestAnimationFrame(function() {
// Move before the three x
for (let i = 0; i < 3; ++i) {
synthesizeKey("KEY_ArrowRight");
}
// Select <span>
synthesizeKey("KEY_ArrowLeft", { shiftKey: true });
document.documentElement.removeAttribute("class");
});
});
</script>

View File

@ -0,0 +1,27 @@
<!doctype html>
<html class="reftest-wait">
<title>Select non-editable content in an editor</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
div:focus {
outline: 3px solid blue;
}
</style>
<div contenteditable="true" spellcheck="false">
xx<img src="image_rgrg-256x256.png">xxx
</div>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('[contenteditable="true"]').focus();
requestAnimationFrame(function() {
// Move after the two x
for (let i = 0; i < 2; ++i) {
synthesizeKey("KEY_ArrowRight");
}
// Select <img>
synthesizeKey("KEY_ArrowRight", { shiftKey: true });
document.documentElement.removeAttribute("class");
});
});
</script>

View File

@ -0,0 +1,27 @@
<!doctype html>
<html class="reftest-wait">
<title>Select non-editable content in an editor</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
div:focus {
outline: 3px solid blue;
}
</style>
<div contenteditable="true" spellcheck="false">
xx<img contenteditable="false" src="image_rgrg-256x256.png">xxx
</div>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('[contenteditable="true"]').focus();
requestAnimationFrame(function() {
// Move after the two x
for (let i = 0; i < 2; ++i) {
synthesizeKey("KEY_ArrowRight");
}
// Select <img>
synthesizeKey("KEY_ArrowRight", { shiftKey: true });
document.documentElement.removeAttribute("class");
});
});
</script>

View File

@ -0,0 +1,27 @@
<!doctype html>
<html class="reftest-wait">
<title>Select non-editable content in an editor</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
div:focus {
outline: 3px solid blue;
}
</style>
<div contenteditable="true" spellcheck="false">
xx<img contenteditable="false" src="image_rgrg-256x256.png">xxx
</div>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('[contenteditable="true"]').focus();
requestAnimationFrame(function() {
// Move before the three x
for (let i = 0; i < 3; ++i) {
synthesizeKey("KEY_ArrowRight");
}
// Select <img>
synthesizeKey("KEY_ArrowLeft", { shiftKey: true });
document.documentElement.removeAttribute("class");
});
});
</script>

View File

@ -4,8 +4,17 @@
type="text/css"?>
<window onload="runTests()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<iframe height="200" width="600" type="content"></iframe>
<iframe height="200" width="600" type="content"></iframe>
<!-- XXXdholbert this wrapper-div and the 'min-height' below are temporary
hacks, to be removed when bug 1602410 lands. They only exist so that
the print-preview area can be sufficiently tall for the previewed
content to be visible in the top left corner of print-preview, in the
face of the "contain"-style scaling & centering that we do.
-->
<div style="overflow:hidden; height: 200px;">
<iframe height="200" width="600" type="content"></iframe>
<iframe height="200" width="600" type="content"
style="min-height:500px"></iframe>
</div>
<script type="application/javascript">
<![CDATA[
var is = window.opener.wrappedJSObject.is;

View File

@ -164,7 +164,7 @@ support-files = preserve3d_sorting_hit_testing_iframe.html
[test_preserve3d_sorting_hit_testing2.html]
support-files = preserve3d_sorting_hit_testing2_iframe.html
[test_reftests_with_caret.html]
skip-if = toolkit == 'android' # Bug 1355842
skip-if = toolkit == 'android' || tsan # android: Bug 1355842. tsan: Bug 1612707
support-files =
bug106855-1.html
bug106855-2.html
@ -367,6 +367,11 @@ support-files =
bug1637476-2-ref.html
bug1637476-3.html
bug1637476-3-ref.html
bug1670531-1.html
bug1670531-2.html
bug1670531-3.html
bug1670531-3-ref.html
bug1670531-4.html
image_rgrg-256x256.png
input-invalid-ref.html
input-maxlength-invalid-change.html

View File

@ -12,7 +12,6 @@
<body>
<script class="testbody" type="application/javascript">
<!--
words = new Array()
function expandStringOffsetToWord(data, offset)
@ -35,14 +34,14 @@ function onContextMenu(e)
function startTest()
{
ta = document.getElementById('blah');
var ta = document.getElementById('blah');
ta.focus();
ta.selectionStart = ta.selectionEnd = ta.value.length;
// Note: This test, intentionally or by accident, relies on sending button '0'
// with contextMenu, which triggers some key-equiv stuff in
// PresShell::AdjustContextMenuKeyEvent.
var mouseParams = { type: 'contextmenu', button: 0 };
// Note: This test, intentionally or by accident, relies on sending button '0'
// with contextMenu, which triggers some key-equiv stuff in
// PresShell::AdjustContextMenuKeyEvent.
var mouseParams = { type: 'contextmenu', button: 0 };
/* Put cursor at start and middle of "sheep" */
synthesizeKey("KEY_ArrowUp")
@ -79,7 +78,6 @@ var mouseParams = { type: 'contextmenu', button: 0 };
SimpleTest.waitForExplicitFinish()
SimpleTest.waitForFocus(startTest)
-->
</script>
<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=370436">Mozilla Bug 370436</a></p>

View File

@ -15,13 +15,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=780847
<body id="body" onload="setTimeout(startTest, 0)" style="margin:0; width:100%; height:100%; overflow:hidden">
<p id="display"></p>
<div id="content">
<!-- XXX Though B2G isn't supported anymore, we probably want to keep this
test's B2G special-cases around, and just make them apply to Android.
(We may need to do so, for this test to be runnable on Android...?)
See bug 1355206 for more.
-->
<!-- the iframe holding this test is only 300px tall on B2G, so we need to
make the t target shorter than normal to test the bottom edge fluffing
<!-- We make the `t` target shorter than normal in case because we test the
bottom edge fluffing on this element, and the test page may be hosted
inside a short iframe in the test harness on some platforms.
-->
<div class="target" style="height:80px" id="t" onmousedown="x=1"></div>
@ -77,7 +73,14 @@ function startTest() {
SimpleTest.waitForExplicitFinish();
let oldResolution = 1.0;
function endTest() {
if (navigator.appVersion.includes("Android")) {
// Restore any resolution that was changed at the end of the test.
let topUtils = SpecialPowers.getDOMWindowUtils(window.top);
topUtils.setResolutionAndScaleTo(oldResolution);
}
SimpleTest.finish();
}
@ -103,15 +106,22 @@ function setShowing(id, show) {
var mm;
function runTest() {
let resolution = 1;
if (SpecialPowers.Services.appinfo.name == "B2G") {
// This test runs on B2G as well, zoomed out. Therefore we need to account
if (navigator.appVersion.includes("Android")) {
// Choose a roundish number for the resolution so that the "midpoint" test below
// doesn't mis-target an element due to rounding error.
let desiredResolution = 0.75;
let topUtils = SpecialPowers.getDOMWindowUtils(window.top);
// Save the old resolution for restoration at the end of the test.
oldResolution = topUtils.getResolution();
topUtils.setResolutionAndScaleTo(desiredResolution);
// This test runs on Android, zoomed out. Therefore we need to account
// for the resolution as well, because the fluff area is relative to screen
// pixels rather than CSS pixels.
let out = {};
SpecialPowers.getDOMWindowUtils(window.top).getResolution(out);
resolution = 1.0 / out.value;
resolution = topUtils.getResolution();
// Make sure we were actually able to zoom out to the desired level.
ok(resolution == desiredResolution, "Resolution is " + resolution);
}
mm = SpecialPowers.getDOMWindowUtils(window.top).physicalMillimeterInCSSPixels * resolution;
mm = SpecialPowers.getDOMWindowUtils(window.top).physicalMillimeterInCSSPixels / resolution;
ok(4*mm >= 10, "WARNING: mm " + mm + " too small in this configuration. Test results will be bogus");
// Test basic functionality: clicks sufficiently close to the element

View File

@ -274,6 +274,10 @@ var tests = [
[ 'bug1637476-1.html' , 'bug1637476-1-ref.html' ] ,
[ 'bug1637476-2.html' , 'bug1637476-2-ref.html' ] ,
[ 'bug1637476-3.html' , 'bug1637476-3-ref.html' ] ,
// shift+arrow key should select non-editable only
[ 'bug1670531-1.html' , 'bug1670531-2.html' ] ,
[ 'bug1670531-3.html' , 'bug1670531-3-ref.html' ] ,
[ 'bug1670531-4.html' , 'bug1670531-3-ref.html' ] ,
function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled_on_touch']]}, nextTest);} ,
function() {SpecialPowers.pushPrefEnv({'set': [['accessibility.browsewithcaret', true]]}, nextTest);} ,
[ 'bug1529492-1.html' , 'bug1529492-1-ref.html' ] ,

View File

@ -39,7 +39,6 @@ LOCAL_INCLUDES += [
'/dom/media',
'/dom/offline',
'/dom/storage',
'/dom/svg',
'/dom/xbl',
'/dom/xslt/base',
'/dom/xslt/xml',

View File

@ -128,15 +128,14 @@ nsContentDLF::CreateInstance(const char* aCommand, nsIChannel* aChannel,
if (knownType) {
viewSourceChannel->SetContentType(type);
} else if (IsImageContentType(type.get())) {
} else if (IsImageContentType(type)) {
// If it's an image, we want to display it the same way we normally would.
// Also note the lifetime of "type" allows us to safely use "get()" here.
contentType = type;
} else {
viewSourceChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
viewSourceChannel->SetContentType(nsLiteralCString(TEXT_PLAIN));
}
} else if (aContentType.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) {
aChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
aChannel->SetContentType(nsLiteralCString(TEXT_PLAIN));
contentType = TEXT_PLAIN;
}
@ -205,7 +204,7 @@ nsContentDLF::CreateInstance(const char* aCommand, nsIChannel* aChannel,
}
// Try image types
if (IsImageContentType(contentType.get())) {
if (IsImageContentType(contentType)) {
return CreateDocument(
aCommand, aChannel, aLoadGroup, aContainer,
[]() -> already_AddRefed<Document> {
@ -266,7 +265,7 @@ already_AddRefed<Document> nsContentDLF::CreateBlankDocument(
// initialize
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank"));
NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
if (!uri) {
return nullptr;
}
@ -390,6 +389,6 @@ nsresult nsContentDLF::CreateXULDocument(
return NS_OK;
}
bool nsContentDLF::IsImageContentType(const char* aContentType) {
bool nsContentDLF::IsImageContentType(const nsACString& aContentType) {
return imgLoader::SupportImageWithMimeType(aContentType);
}

View File

@ -54,7 +54,7 @@ class nsContentDLF final : public nsIDocumentLoaderFactory {
private:
static nsresult EnsureUAStyleSheet();
static bool IsImageContentType(const char* aContentType);
static bool IsImageContentType(const nsACString&);
};
nsresult NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult);

View File

@ -51,8 +51,7 @@
#include "nsFocusManager.h"
#include "nsListControlFrame.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "SVGElementFactory.h"
#include "nsSVGUtils.h"
#include "mozilla/dom/SVGElementFactory.h"
#include "nsMathMLAtoms.h"
#include "nsMathMLOperators.h"
#include "Navigator.h"
@ -123,6 +122,7 @@
#include "mozilla/dom/quota/ActorsParent.h"
#include "mozilla/dom/localstorage/ActorsParent.h"
#include "mozilla/net/UrlClassifierFeatureFactory.h"
#include "nsLayoutUtils.h"
#include "nsThreadManager.h"
#include "mozilla/css/ImageLoader.h"
#include "gfxUserFontSet.h"
@ -305,7 +305,6 @@ void nsLayoutStatics::Shutdown() {
if (XRE_IsParentProcess() || XRE_IsContentProcess()) {
ShutdownServo();
URLExtraData::ReleaseDummy();
}
mozilla::dom::AbstractRange::Shutdown();

View File

@ -0,0 +1,8 @@
<style>
* {
rotate: 0.8339rad;
inset: 84pt -15742cm 8% ! important;
position: fixed;
}
</style>
<button>

View File

@ -80,5 +80,6 @@ load 1488219.html
load 1600207.html
load 1600367.html
load 1617753.html
load 1679471.html
load 1690166-1.html
load 1690166-2.html

View File

@ -2,52 +2,51 @@
# 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/.
with Files('**'):
BUG_COMPONENT = ('Core', 'Layout: Form Controls')
with Files("**"):
BUG_COMPONENT = ("Core", "Layout: Form Controls")
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
MOCHITEST_MANIFESTS += ["test/mochitest.ini"]
MOCHITEST_CHROME_MANIFESTS += ["test/chrome.ini"]
EXPORTS += [
'nsIFormControlFrame.h',
'nsISelectControlFrame.h',
'nsITextControlFrame.h',
"nsIFormControlFrame.h",
"nsISelectControlFrame.h",
"nsITextControlFrame.h",
]
UNIFIED_SOURCES += [
'nsButtonFrameRenderer.cpp',
'nsCheckboxRadioFrame.cpp',
'nsColorControlFrame.cpp',
'nsComboboxControlFrame.cpp',
'nsDateTimeControlFrame.cpp',
'nsFieldSetFrame.cpp',
'nsFileControlFrame.cpp',
'nsGfxButtonControlFrame.cpp',
'nsHTMLButtonControlFrame.cpp',
'nsImageControlFrame.cpp',
'nsLegendFrame.cpp',
'nsListControlFrame.cpp',
'nsMeterFrame.cpp',
'nsNumberControlFrame.cpp',
'nsProgressFrame.cpp',
'nsRangeFrame.cpp',
'nsSelectsAreaFrame.cpp',
'nsTextControlFrame.cpp',
"nsButtonFrameRenderer.cpp",
"nsCheckboxRadioFrame.cpp",
"nsColorControlFrame.cpp",
"nsComboboxControlFrame.cpp",
"nsDateTimeControlFrame.cpp",
"nsFieldSetFrame.cpp",
"nsFileControlFrame.cpp",
"nsGfxButtonControlFrame.cpp",
"nsHTMLButtonControlFrame.cpp",
"nsImageControlFrame.cpp",
"nsListControlFrame.cpp",
"nsMeterFrame.cpp",
"nsNumberControlFrame.cpp",
"nsProgressFrame.cpp",
"nsRangeFrame.cpp",
"nsSelectsAreaFrame.cpp",
"nsTextControlFrame.cpp",
]
FINAL_LIBRARY = 'xul'
FINAL_LIBRARY = "xul"
include('/ipc/chromium/chromium-config.mozbuild')
include("/ipc/chromium/chromium-config.mozbuild")
LOCAL_INCLUDES += [
'../base',
'../generic',
'../painting',
'../style',
'../xul',
'/dom/base',
'/dom/html',
"../base",
"../generic",
"../painting",
"../style",
"../xul",
"/dom/base",
"/dom/html",
]
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']
if CONFIG["CC_TYPE"] in ("clang", "gcc"):
CXXFLAGS += ["-Wno-error=shadow"]

View File

@ -49,8 +49,7 @@ nsIFrame* nsButtonFrameRenderer::GetFrame() { return mFrame; }
void nsButtonFrameRenderer::SetDisabled(bool aDisabled, bool aNotify) {
dom::Element* element = mFrame->GetContent()->AsElement();
if (aDisabled)
element->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, EmptyString(),
aNotify);
element->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, u""_ns, aNotify);
else
element->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
}
@ -89,7 +88,7 @@ class nsDisplayButtonBoxShadowOuter : public nsPaintedDisplayItem {
nsRect nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const {
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
return mFrame->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
}
void nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
@ -293,8 +292,7 @@ nsRect nsDisplayButtonBorder::GetBounds(nsDisplayListBuilder* aBuilder,
*aSnap = false;
return aBuilder->IsForEventDelivery()
? nsRect(ToReferenceFrame(), mFrame->GetSize())
: mFrame->GetVisualOverflowRectRelativeToSelf() +
ToReferenceFrame();
: mFrame->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
}
class nsDisplayButtonForeground final : public nsPaintedDisplayItem {

View File

@ -65,7 +65,7 @@ nscoord nsCheckboxRadioFrame::GetPrefISize(gfxContext* aRenderingContext) {
LogicalSize nsCheckboxRadioFrame::ComputeAutoSize(
gfxContext* aRC, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorder, const LogicalSize& aPadding,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
LogicalSize size(aWM, 0, 0);
if (!StyleDisplay()->HasAppearance()) {
@ -74,14 +74,15 @@ LogicalSize nsCheckboxRadioFrame::ComputeAutoSize(
// Note: this call always set the BSize to NS_UNCONSTRAINEDSIZE.
size = nsAtomicContainerFrame::ComputeAutoSize(
aRC, aWM, aCBSize, aAvailableISize, aMargin, aBorder, aPadding, aFlags);
aRC, aWM, aCBSize, aAvailableISize, aMargin, aBorderPadding,
aSizeOverrides, aFlags);
size.BSize(aWM) = DefaultSize();
return size;
}
nscoord nsCheckboxRadioFrame::GetLogicalBaseline(
WritingMode aWritingMode) const {
NS_ASSERTION(!NS_SUBTREE_DIRTY(this), "frame must not be dirty");
NS_ASSERTION(!IsSubtreeDirty(), "frame must not be dirty");
// For appearance:none we use a standard CSS baseline, i.e. synthesized from
// our margin-box.
@ -119,8 +120,8 @@ void nsCheckboxRadioFrame::Reflow(nsPresContext* aPresContext,
RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
}
aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
aReflowInput.ComputedSizeWithBorderPadding());
const auto wm = aReflowInput.GetWritingMode();
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
float inflation = nsLayoutUtils::FontSizeInflationFor(this);

View File

@ -46,11 +46,13 @@ class nsCheckboxRadioFrame final : public nsAtomicContainerFrame,
/**
* Our auto size is just intrinsic width and intrinsic height.
*/
virtual mozilla::LogicalSize ComputeAutoSize(
mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
/**
* Respond to a gui event

View File

@ -46,7 +46,7 @@ void nsColorControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
#ifdef DEBUG_FRAME_DUMP
nsresult nsColorControlFrame::GetFrameName(nsAString& aResult) const {
return MakeFrameName(NS_LITERAL_STRING("ColorControl"), aResult);
return MakeFrameName(u"ColorControl"_ns, aResult);
}
#endif
@ -103,7 +103,7 @@ nsresult nsColorControlFrame::UpdateColor() {
// Set the background-color CSS property of the swatch element to this color.
return mColorContent->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
NS_LITERAL_STRING("background-color:") + color,
u"background-color:"_ns + color,
/* aNotify */ true);
}

View File

@ -15,6 +15,7 @@
#include "nsCSSAnonBoxes.h"
#include "nsHTMLParts.h"
#include "nsIFormControl.h"
#include "nsILayoutHistoryState.h"
#include "nsNameSpaceManager.h"
#include "nsListControlFrame.h"
#include "nsPIDOMWindow.h"
@ -400,7 +401,7 @@ void nsComboboxControlFrame::ReflowDropdown(nsPresContext* aPresContext,
// don't even need to cache mDropdownFrame's ascent or anything. If we don't
// need to reflow it, just bail out here.
if (!aReflowInput.ShouldReflowAllKids() &&
!NS_SUBTREE_DIRTY(mDropdownFrame)) {
!mDropdownFrame->IsSubtreeDirty()) {
return;
}
@ -419,8 +420,8 @@ void nsComboboxControlFrame::ReflowDropdown(nsPresContext* aPresContext,
// both sets of mComputedBorderPadding.
nscoord forcedISize =
aReflowInput.ComputedISize() +
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm) -
kidReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm);
aReflowInput.ComputedLogicalBorderPadding(wm).IStartEnd(wm) -
kidReflowInput.ComputedLogicalBorderPadding(wm).IStartEnd(wm);
kidReflowInput.SetComputedISize(
std::max(kidReflowInput.ComputedISize(), forcedISize));
@ -463,7 +464,8 @@ nsPoint nsComboboxControlFrame::GetCSSTransformTranslation() {
Matrix transform;
while (frame) {
nsIFrame* parent;
Matrix4x4Flagged ctm = frame->GetTransformMatrix(nullptr, &parent);
Matrix4x4Flagged ctm = frame->GetTransformMatrix(
ViewportType::Layout, RelativeTo{nullptr}, &parent);
Matrix matrix;
if (ctm.Is2D(&matrix)) {
transform = transform * matrix;
@ -566,7 +568,7 @@ void nsComboboxControlFrame::GetAvailableDropdownSpace(
}
nscoord minBCoord;
nsPresContext* pc = PresContext()->GetToplevelContentDocumentPresContext();
nsPresContext* pc = PresContext()->GetInProcessRootContentDocumentPresContext();
nsIFrame* root = pc ? pc->PresShell()->GetRootFrame() : nullptr;
if (root) {
minBCoord = LogicalRect(aWM, root->GetScreenRectInAppUnits(), containerSize)
@ -703,8 +705,8 @@ bool nsComboboxControlFrame::HasDropDownButton() const {
PresContext()->Theme()->ThemeNeedsComboboxDropmarker());
}
nscoord nsComboboxControlFrame::GetIntrinsicISize(
gfxContext* aRenderingContext, nsLayoutUtils::IntrinsicISizeType aType) {
nscoord nsComboboxControlFrame::GetIntrinsicISize(gfxContext* aRenderingContext,
IntrinsicISizeType aType) {
// get the scrollbar width, we'll use this later
nscoord scrollbarWidth = 0;
nsPresContext* presContext = PresContext();
@ -731,14 +733,14 @@ nscoord nsComboboxControlFrame::GetIntrinsicISize(
nscoord dropdownContentISize;
bool isUsingOverlayScrollbars =
LookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) != 0;
if (aType == nsLayoutUtils::MIN_ISIZE) {
if (aType == IntrinsicISizeType::MinISize) {
dropdownContentISize =
isContainSize ? 0 : mDropdownFrame->GetMinISize(aRenderingContext);
if (isUsingOverlayScrollbars) {
dropdownContentISize += scrollbarWidth;
}
} else {
NS_ASSERTION(aType == nsLayoutUtils::PREF_ISIZE, "Unexpected type");
NS_ASSERTION(aType == IntrinsicISizeType::PrefISize, "Unexpected type");
dropdownContentISize =
isContainSize ? 0 : mDropdownFrame->GetPrefISize(aRenderingContext);
if (isUsingOverlayScrollbars) {
@ -762,14 +764,15 @@ nscoord nsComboboxControlFrame::GetIntrinsicISize(
nscoord nsComboboxControlFrame::GetMinISize(gfxContext* aRenderingContext) {
nscoord minISize;
DISPLAY_MIN_INLINE_SIZE(this, minISize);
minISize = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::MIN_ISIZE);
minISize = GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::MinISize);
return minISize;
}
nscoord nsComboboxControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
nscoord prefISize;
DISPLAY_PREF_INLINE_SIZE(this, prefISize);
prefISize = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::PREF_ISIZE);
prefISize =
GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::PrefISize);
return prefISize;
}
@ -833,19 +836,18 @@ void nsComboboxControlFrame::Reflow(nsPresContext* aPresContext,
mDisplayISize = aReflowInput.ComputedISize() - buttonISize;
mMaxDisplayISize =
mDisplayISize + aReflowInput.ComputedLogicalPadding().IEnd(wm);
mDisplayISize + aReflowInput.ComputedLogicalPadding(wm).IEnd(wm);
nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
// The button should occupy the same space as a scrollbar
nsSize containerSize = aDesiredSize.PhysicalSize();
LogicalRect buttonRect = mButtonFrame->GetLogicalRect(containerSize);
const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(wm);
buttonRect.IStart(wm) =
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm) +
mDisplayISize -
(aReflowInput.ComputedLogicalBorderPadding().IEnd(wm) -
aReflowInput.ComputedLogicalPadding().IEnd(wm));
buttonRect.IStart(wm) = borderPadding.IStartEnd(wm) + mDisplayISize -
(borderPadding.IEnd(wm) -
aReflowInput.ComputedLogicalPadding(wm).IEnd(wm));
buttonRect.ISize(wm) = buttonISize;
buttonRect.BStart(wm) = this->GetLogicalUsedBorder(wm).BStart(wm);
@ -865,7 +867,7 @@ void nsComboboxControlFrame::Reflow(nsPresContext* aPresContext,
#ifdef DEBUG_FRAME_DUMP
nsresult nsComboboxControlFrame::GetFrameName(nsAString& aResult) const {
return MakeFrameName(NS_LITERAL_STRING("ComboboxControl"), aResult);
return MakeFrameName(u"ComboboxControl"_ns, aResult);
}
#endif
@ -1170,20 +1172,18 @@ nsresult nsComboboxControlFrame::CreateAnonymousContent(
// make someone to listen to the button. If its pressed by someone like
// Accessibility then open or close the combo box.
mButtonListener = new nsComboButtonListener(this);
mButtonContent->AddEventListener(NS_LITERAL_STRING("click"), mButtonListener,
false, false);
mButtonContent->AddEventListener(u"click"_ns, mButtonListener, false, false);
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
NS_LITERAL_STRING("button"), false);
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, u"button"_ns,
false);
// Set tabindex="-1" so that the button is not tabbable
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::tabindex,
NS_LITERAL_STRING("-1"), false);
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, u"-1"_ns,
false);
WritingMode wm = GetWritingMode();
if (wm.IsVertical()) {
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orientation,
wm.IsVerticalRL() ? NS_LITERAL_STRING("left")
: NS_LITERAL_STRING("right"),
wm.IsVerticalRL() ? u"left"_ns : u"right"_ns,
false);
}
@ -1222,7 +1222,7 @@ class nsComboboxDisplayFrame final : public nsBlockFrame {
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("ComboboxDisplay"), aResult);
return MakeFrameName(u"ComboboxDisplay"_ns, aResult);
}
#endif
@ -1252,7 +1252,7 @@ void nsComboboxDisplayFrame::Reflow(nsPresContext* aPresContext,
ReflowInput state(aReflowInput);
WritingMode wm = aReflowInput.GetWritingMode();
LogicalMargin bp = state.ComputedLogicalBorderPadding();
LogicalMargin bp = state.ComputedLogicalBorderPadding(wm);
if (state.ComputedBSize() == NS_UNCONSTRAINEDSIZE) {
float inflation = nsLayoutUtils::FontSizeInflationFor(mComboBox);
// We intentionally use the combobox frame's style here, which has
@ -1339,6 +1339,10 @@ nsIFrame* nsComboboxControlFrame::CreateFrameForDisplayNode() {
return mDisplayFrame;
}
nsIScrollableFrame* nsComboboxControlFrame::GetScrollTargetFrame() const {
return do_QueryFrame(mDropdownFrame);
}
void nsComboboxControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) {
if (sFocused == this) {
@ -1570,9 +1574,8 @@ nsComboboxControlFrame::OnOptionSelected(int32_t aIndex, bool aSelected) {
void nsComboboxControlFrame::FireValueChangeEvent() {
// Fire ValueChange event to indicate data value of combo box has changed
nsContentUtils::AddScriptRunner(
new AsyncEventDispatcher(mContent, NS_LITERAL_STRING("ValueChange"),
CanBubble::eYes, ChromeOnlyDispatch::eNo));
nsContentUtils::AddScriptRunner(new AsyncEventDispatcher(
mContent, u"ValueChange"_ns, CanBubble::eYes, ChromeOnlyDispatch::eNo));
}
void nsComboboxControlFrame::OnContentReset() {

View File

@ -100,9 +100,7 @@ class nsComboboxControlFrame final : public nsBlockFrame,
aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
virtual nsIScrollableFrame* GetScrollTargetFrame() override {
return do_QueryFrame(mDropdownFrame);
}
virtual nsIScrollableFrame* GetScrollTargetFrame() const override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
@ -238,7 +236,7 @@ class nsComboboxControlFrame final : public nsBlockFrame,
// Helper for GetMinISize/GetPrefISize
nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
nsLayoutUtils::IntrinsicISizeType aType);
mozilla::IntrinsicISizeType aType);
class RedisplayTextEvent : public mozilla::Runnable {
public:

View File

@ -48,7 +48,7 @@ nscoord nsDateTimeControlFrame::GetMinISize(gfxContext* aRenderingContext) {
nsIFrame* kid = mFrames.FirstChild();
if (kid) { // display:none?
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
nsLayoutUtils::MIN_ISIZE);
IntrinsicISizeType::MinISize);
} else {
result = 0;
}
@ -62,8 +62,8 @@ nscoord nsDateTimeControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
nsIFrame* kid = mFrames.FirstChild();
if (kid) { // display:none?
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
nsLayoutUtils::PREF_ISIZE);
result = nsLayoutUtils::IntrinsicForContainer(
aRenderingContext, kid, IntrinsicISizeType::PrefISize);
} else {
result = 0;
}
@ -97,23 +97,20 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
// Figure out our border-box sizes as well (by adding borderPadding to
// content-box sizes):
const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(myWM);
const nscoord borderBoxISize =
contentBoxISize +
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(myWM);
contentBoxISize + borderPadding.IStartEnd(myWM);
nscoord borderBoxBSize;
if (contentBoxBSize != NS_UNCONSTRAINEDSIZE) {
borderBoxBSize =
contentBoxBSize +
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
borderBoxBSize = contentBoxBSize + borderPadding.BStartEnd(myWM);
} // else, we'll figure out borderBoxBSize after we resolve contentBoxBSize.
nsIFrame* inputAreaFrame = mFrames.FirstChild();
if (!inputAreaFrame) { // display:none?
if (contentBoxBSize == NS_UNCONSTRAINEDSIZE) {
contentBoxBSize = 0;
borderBoxBSize =
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
borderBoxBSize = borderPadding.BStartEnd(myWM);
}
} else {
ReflowOutput childDesiredSize(aReflowInput);
@ -122,27 +119,23 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
LogicalSize availSize = aReflowInput.ComputedSize(wm);
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput childReflowOuput(aPresContext, aReflowInput, inputAreaFrame,
ReflowInput childReflowInput(aPresContext, aReflowInput, inputAreaFrame,
availSize);
// Convert input area margin into my own writing-mode (in case it differs):
LogicalMargin childMargin =
childReflowOuput.ComputedLogicalMargin().ConvertTo(myWM, wm);
LogicalMargin childMargin = childReflowInput.ComputedLogicalMargin(myWM);
// offsets of input area frame within this frame:
LogicalPoint childOffset(
myWM,
aReflowInput.ComputedLogicalBorderPadding().IStart(myWM) +
childMargin.IStart(myWM),
aReflowInput.ComputedLogicalBorderPadding().BStart(myWM) +
childMargin.BStart(myWM));
myWM, borderPadding.IStart(myWM) + childMargin.IStart(myWM),
borderPadding.BStart(myWM) + childMargin.BStart(myWM));
nsReflowStatus childStatus;
// We initially reflow the child with a dummy containerSize; positioning
// will be fixed later.
const nsSize dummyContainerSize;
ReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
childReflowOuput, myWM, childOffset, dummyContainerSize,
childReflowInput, myWM, childOffset, dummyContainerSize,
ReflowChildFlags::Default, childStatus);
MOZ_ASSERT(childStatus.IsFullyComplete(),
"We gave our child unconstrained available block-size, "
@ -165,9 +158,7 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
NS_CSS_MINMAX(contentBoxBSize, aReflowInput.ComputedMinBSize(),
aReflowInput.ComputedMaxBSize());
borderBoxBSize =
contentBoxBSize +
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
borderBoxBSize = contentBoxBSize + borderPadding.BStartEnd(myWM);
}
// Center child in block axis
@ -180,10 +171,11 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
// Place the child
FinishReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
&childReflowOuput, myWM, childOffset, borderBoxSize,
&childReflowInput, myWM, childOffset, borderBoxSize,
ReflowChildFlags::Default);
if (!aReflowInput.mStyleDisplay->IsContainLayout()) {
if (!aReflowInput.mStyleDisplay->IsContainLayout() &&
childDesiredSize.BlockStartAscent() != ReflowOutput::ASK_FOR_BASELINE) {
nsSize contentBoxSize =
LogicalSize(myWM, contentBoxISize, contentBoxBSize)
.GetPhysicalSize(myWM);
@ -191,7 +183,7 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
childDesiredSize.BlockStartAscent() +
inputAreaFrame->BStart(aReflowInput.GetWritingMode(),
contentBoxSize));
} // else: we're layout-contained, and so we have no baseline.
} // else, leave ascent unset (we don't have one or don't know it)
}
LogicalSize logicalDesiredSize(myWM, borderBoxISize, borderBoxBSize);

View File

@ -41,7 +41,7 @@ class nsDateTimeControlFrame final : public nsContainerFrame {
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("DateTimeControl"), aResult);
return MakeFrameName(u"DateTimeControl"_ns, aResult);
}
#endif

View File

@ -11,14 +11,18 @@
#include "mozilla/Likely.h"
#include "mozilla/PresShell.h"
#include "mozilla/Maybe.h"
#include "nsBlockFrame.h"
#include "nsCSSAnonBoxes.h"
#include "nsCSSFrameConstructor.h"
#include "nsCSSRendering.h"
#include "nsDisplayList.h"
#include "nsGkAtoms.h"
#include "nsIFrameInlines.h"
#include "nsLayoutUtils.h"
#include "nsLegendFrame.h"
#include "nsStyleConsts.h"
#ifdef MOZ_BUILD_WEBRENDER
# include "mozilla/webrender/WebRenderAPI.h"
#endif
using namespace mozilla;
using namespace mozilla::gfx;
@ -156,7 +160,7 @@ nsRect nsDisplayFieldSetBorder::GetBounds(nsDisplayListBuilder* aBuilder,
// nsDisplayBorder has here, but keeping things in sync would be a pain, and
// this code is not typically performance-sensitive.
*aSnap = false;
return Frame()->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
return Frame()->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
}
#ifdef MOZ_BUILD_WEBRENDER
@ -187,7 +191,7 @@ bool nsDisplayFieldSetBorder::CreateWebRenderCommands(
// We need to clip out the part of the border where the legend would go
auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
auto layoutRect = wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
frame->GetVisualOverflowRectRelativeToSelf() + offset,
frame->InkOverflowRectRelativeToSelf() + offset,
appUnitsPerDevPixel));
wr::ComplexClipRegion region;
@ -311,17 +315,16 @@ image::ImgDrawResult nsFieldSetFrame::PaintBorder(
// We set up a clip path which has our rect clockwise and the legend rect
// counterclockwise, with FILL_WINDING as the fill rule. That will allow us
// to paint within our rect but outside the legend rect. For "our rect" we
// use our visual overflow rect (relative to ourselves, so it's not affected
// use our ink overflow rect (relative to ourselves, so it's not affected
// by transforms), because we can have borders sticking outside our border
// box (e.g. due to border-image-outset).
RefPtr<PathBuilder> pathBuilder =
drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
AppendRectToPath(
pathBuilder,
NSRectToSnappedRect(GetVisualOverflowRectRelativeToSelf() + aPt,
appUnitsPerDevPixel, *drawTarget),
true);
AppendRectToPath(pathBuilder,
NSRectToSnappedRect(InkOverflowRectRelativeToSelf() + aPt,
appUnitsPerDevPixel, *drawTarget),
true);
AppendRectToPath(
pathBuilder,
NSRectToSnappedRect(legendRect, appUnitsPerDevPixel, *drawTarget),
@ -343,8 +346,8 @@ image::ImgDrawResult nsFieldSetFrame::PaintBorder(
return result;
}
nscoord nsFieldSetFrame::GetIntrinsicISize(
gfxContext* aRenderingContext, nsLayoutUtils::IntrinsicISizeType aType) {
nscoord nsFieldSetFrame::GetIntrinsicISize(gfxContext* aRenderingContext,
IntrinsicISizeType aType) {
nscoord legendWidth = 0;
nscoord contentWidth = 0;
if (!StyleDisplay()->IsContainSize()) {
@ -371,7 +374,7 @@ nscoord nsFieldSetFrame::GetMinISize(gfxContext* aRenderingContext) {
nscoord result = 0;
DISPLAY_MIN_INLINE_SIZE(this, result);
result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::MIN_ISIZE);
result = GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::MinISize);
return result;
}
@ -379,7 +382,7 @@ nscoord nsFieldSetFrame::GetPrefISize(gfxContext* aRenderingContext) {
nscoord result = 0;
DISPLAY_PREF_INLINE_SIZE(this, result);
result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::PREF_ISIZE);
result = GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::PrefISize);
return result;
}
@ -388,7 +391,7 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
using LegendAlignValue = HTMLLegendElement::LegendAlignValue;
using LegendAlignValue = mozilla::dom::HTMLLegendElement::LegendAlignValue;
MarkInReflow();
DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
@ -397,7 +400,7 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
NS_WARNING_ASSERTION(aReflowInput.ComputedISize() != NS_UNCONSTRAINEDSIZE,
"Should have a precomputed inline-size!");
nsOverflowAreas ocBounds;
OverflowAreas ocBounds;
nsReflowStatus ocStatus;
auto* prevInFlow = static_cast<nsFieldSetFrame*>(GetPrevInFlow());
if (prevInFlow) {
@ -427,15 +430,15 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
reflowInner = inner != nullptr;
reflowLegend = legend != nullptr;
} else {
reflowInner = inner && NS_SUBTREE_DIRTY(inner);
reflowLegend = legend && NS_SUBTREE_DIRTY(legend);
reflowInner = inner && inner->IsSubtreeDirty();
reflowLegend = legend && legend->IsSubtreeDirty();
}
// @note |this| frame applies borders but not any padding. Our anonymous
// inner frame applies the padding (but not borders).
const auto wm = GetWritingMode();
LogicalMargin border = aReflowInput.ComputedLogicalBorderPadding() -
aReflowInput.ComputedLogicalPadding();
LogicalMargin border = aReflowInput.ComputedLogicalBorderPadding(wm) -
aReflowInput.ComputedLogicalPadding(wm);
auto skipSides = PreReflowBlockLevelLogicalSkipSides();
border.ApplySkipSides(skipSides);
LogicalSize availSize(wm, aReflowInput.ComputedSize().ISize(wm),
@ -447,8 +450,15 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
if (legend) {
const auto legendWM = legend->GetWritingMode();
LogicalSize legendAvailSize = availSize.ConvertTo(legendWM, wm);
ComputeSizeFlags sizeFlags;
if (legend->StylePosition()->ISize(wm).IsAuto()) {
sizeFlags = ComputeSizeFlag::ShrinkWrap;
}
ReflowInput::InitFlags initFlags; // intentionally empty
StyleSizeOverrides sizeOverrides; // intentionally empty
legendReflowInput.emplace(aPresContext, aReflowInput, legend,
legendAvailSize);
legendAvailSize, Nothing(), initFlags,
sizeOverrides, sizeFlags);
}
const bool avoidBreakInside = ShouldAvoidBreakInside(aReflowInput);
if (reflowLegend) {
@ -548,7 +558,8 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
(LogicalSize(wm, 0, mLegendSpace) + border.Size(wm)).GetPhysicalSize(wm);
if (reflowInner) {
LogicalSize innerAvailSize = availSize;
innerAvailSize.ISize(wm) = aReflowInput.ComputedSizeWithPadding().ISize(wm);
innerAvailSize.ISize(wm) =
aReflowInput.ComputedSizeWithPadding(wm).ISize(wm);
nscoord remainingComputedBSize = aReflowInput.ComputedBSize();
if (prevInFlow && remainingComputedBSize != NS_UNCONSTRAINEDSIZE) {
// Subtract the consumed BSize associated with the legend.
@ -565,7 +576,8 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
StyleBoxDecorationBreak::Clone &&
(aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
remainingComputedBSize +
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm) >=
aReflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(
wm) >=
availSize.BSize(wm))) {
innerAvailSize.BSize(wm) -= border.BEnd(wm);
}
@ -573,10 +585,11 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
}
ReflowInput kidReflowInput(aPresContext, aReflowInput, inner,
innerAvailSize, Nothing(),
ReflowInput::CALLER_WILL_INIT);
ReflowInput::InitFlag::CallerWillInit);
// Override computed padding, in case it's percentage padding
kidReflowInput.Init(aPresContext, Nothing(), nullptr,
&aReflowInput.ComputedPhysicalPadding());
kidReflowInput.Init(
aPresContext, Nothing(), Nothing(),
Some(aReflowInput.ComputedLogicalPadding(inner->GetWritingMode())));
if (kidReflowInput.mFlags.mIsTopOfPage) {
// Prevent break-before from |inner| if we have a legend.
kidReflowInput.mFlags.mIsTopOfPage = !legend;
@ -670,17 +683,16 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// The legend is positioned inline-wards within the inner's content rect
// (so that padding on the fieldset affects the legend position).
LogicalRect innerContentRect = contentRect;
innerContentRect.Deflate(wm, aReflowInput.ComputedLogicalPadding());
innerContentRect.Deflate(wm, aReflowInput.ComputedLogicalPadding(wm));
// If the inner content rect is larger than the legend, we can align the
// legend.
if (innerContentRect.ISize(wm) > mLegendRect.ISize(wm)) {
// NOTE legend @align values are: left/right/center
// GetLogicalAlign converts left/right to start/end for the given WM.
// @see HTMLLegendElement::ParseAttribute, nsLegendFrame::GetLogicalAlign
LegendAlignValue align =
static_cast<nsLegendFrame*>(legend->GetContentInsertionFrame())
->GetLogicalAlign(wm);
switch (align) {
// @see HTMLLegendElement::ParseAttribute/LogicalAlign
auto* legendElement =
dom::HTMLLegendElement::FromNode(legend->GetContent());
switch (legendElement->LogicalAlign(wm)) {
case LegendAlignValue::InlineEnd:
mLegendRect.IStart(wm) =
innerContentRect.IEnd(wm) - mLegendRect.ISize(wm);
@ -709,9 +721,7 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
// Note that legend's writing mode may be different from the fieldset's,
// so we need to convert offsets before applying them to it (bug 1134534).
LogicalMargin offsets =
legendReflowInput->ComputedLogicalOffsets().ConvertTo(
wm, legendReflowInput->GetWritingMode());
LogicalMargin offsets = legendReflowInput->ComputedLogicalOffsets(wm);
ReflowInput::ApplyRelativePositioning(legend, wm, offsets, &actualLegendPos,
containerSize);
@ -744,7 +754,7 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
: aReflowInput.ComputedBSize();
finalSize.BSize(wm) =
contentBoxBSize +
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm);
aReflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(wm);
}
if (aStatus.IsComplete() &&
@ -792,24 +802,46 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
#ifdef DEBUG
void nsFieldSetFrame::SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList) {
nsContainerFrame::SetInitialChildList(aListID, aChildList);
MOZ_ASSERT(aListID != kPrincipalList || GetInner(),
"Setting principal child list should populate our inner frame");
if (nsBlockFrame* legend = do_QueryFrame(GetLegend())) {
// A rendered legend always establish a new formatting context.
// https://html.spec.whatwg.org/multipage/rendering.html#rendered-legend
legend->AddStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS);
}
MOZ_ASSERT(aListID != kPrincipalList || GetInner() || GetLegend(),
"Setting principal child list should populate our inner frame "
"or our rendered legend");
}
void nsFieldSetFrame::AppendFrames(ChildListID aListID,
nsFrameList& aFrameList) {
MOZ_CRASH("nsFieldSetFrame::AppendFrames not supported");
MOZ_ASSERT(aListID == kNoReflowPrincipalList &&
HasAnyStateBits(NS_FRAME_FIRST_REFLOW),
"AppendFrames should only be used from "
"nsCSSFrameConstructor::ConstructFieldSetFrame");
nsContainerFrame::AppendFrames(aListID, aFrameList);
MOZ_ASSERT(GetInner(), "at this point we should have an inner frame");
}
void nsFieldSetFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
const nsLineList::iterator* aPrevFrameLine,
nsFrameList& aFrameList) {
MOZ_CRASH("nsFieldSetFrame::InsertFrames not supported");
MOZ_ASSERT(aListID == kPrincipalList && !aPrevFrame && !GetLegend(),
"InsertFrames should only be used to prepend a rendered legend "
"from nsCSSFrameConstructor::ConstructFramesFromItemList");
nsContainerFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine,
aFrameList);
MOZ_ASSERT(GetLegend());
if (nsBlockFrame* legend = do_QueryFrame(GetLegend())) {
// A rendered legend always establish a new formatting context.
// https://html.spec.whatwg.org/multipage/rendering.html#rendered-legend
legend->AddStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS);
}
}
#ifdef DEBUG
void nsFieldSetFrame::RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) {
MOZ_CRASH("nsFieldSetFrame::RemoveFrame not supported");
}
@ -919,18 +951,16 @@ void nsFieldSetFrame::EnsureChildContinuation(nsIFrame* aChild,
}
}
if (aStatus.IsOverflowIncomplete()) {
if (nsFrameList* eoc =
GetPropTableFrames(ExcessOverflowContainersProperty())) {
if (nsFrameList* eoc = GetExcessOverflowContainers()) {
eoc->AppendFrames(nullptr, nifs);
} else {
SetPropTableFrames(new (PresShell()) nsFrameList(nifs),
ExcessOverflowContainersProperty());
SetExcessOverflowContainers(std::move(nifs));
}
} else {
if (nsFrameList* oc = GetOverflowFrames()) {
oc->AppendFrames(nullptr, nifs);
} else {
SetOverflowFrames(nifs);
SetOverflowFrames(std::move(nifs));
}
}
}

View File

@ -19,7 +19,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
explicit nsFieldSetFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
nsLayoutUtils::IntrinsicISizeType);
mozilla::IntrinsicISizeType);
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
@ -47,7 +47,6 @@ class nsFieldSetFrame final : public nsContainerFrame {
gfxContext& aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect);
#ifdef DEBUG
virtual void SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList) override;
virtual void AppendFrames(ChildListID aListID,
@ -55,6 +54,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
const nsLineList::iterator* aPrevFrameLine,
nsFrameList& aFrameList) override;
#ifdef DEBUG
virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
#endif
@ -62,7 +62,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
return nsContainerFrame::IsFrameOfType(
aFlags & ~nsIFrame::eCanContainOverflowContainers);
}
virtual nsIScrollableFrame* GetScrollTargetFrame() override {
virtual nsIScrollableFrame* GetScrollTargetFrame() const override {
return do_QueryFrame(GetInner());
}
@ -75,7 +75,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult);
return MakeFrameName(u"FieldSet"_ns, aResult);
}
#endif
@ -90,9 +90,8 @@ class nsFieldSetFrame final : public nsContainerFrame {
nsContainerFrame* GetInner() const;
/**
* Return the frame that represents the legend if any. This may be
* a nsLegendFrame or a nsHTMLScrollFrame with the nsLegendFrame as the
* scrolled frame (aka content insertion frame).
* Return the frame that represents the rendered legend if any.
* https://html.spec.whatwg.org/multipage/rendering.html#rendered-legend
*/
nsIFrame* GetLegend() const;

View File

@ -164,10 +164,12 @@ void nsFileControlFrame::Reflow(nsPresContext* aPresContext,
labelBP +=
lastLabelCont->GetLogicalUsedBorderAndPadding(wm).IStartEnd(wm);
}
auto* buttonFrame = mBrowseFilesOrDirs->GetPrimaryFrame();
nscoord availableISizeForLabel =
contentISize - buttonFrame->ISize(wm) -
buttonFrame->GetLogicalUsedMargin(wm).IStartEnd(wm);
nscoord availableISizeForLabel = contentISize;
if (auto* buttonFrame = mBrowseFilesOrDirs->GetPrimaryFrame()) {
availableISizeForLabel -=
buttonFrame->ISize(wm) +
buttonFrame->GetLogicalUsedMargin(wm).IStartEnd(wm);
}
if (CropTextToWidth(*aReflowInput.mRenderingContext, labelFrame,
availableISizeForLabel - labelBP, filename)) {
nsBlockFrame::DidReflow(aPresContext, &aReflowInput);
@ -190,10 +192,8 @@ void nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
// Remove the events.
if (mContent) {
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("drop"),
mMouseListener, false);
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, false);
mContent->RemoveSystemEventListener(u"drop"_ns, mMouseListener, false);
mContent->RemoveSystemEventListener(u"dragover"_ns, mMouseListener, false);
}
aPostDestroyData.AddAnonymousContent(mTextContent.forget());
@ -211,7 +211,7 @@ static already_AddRefed<Element> MakeAnonButton(Document* aDoc,
// NOTE: SetIsNativeAnonymousRoot() has to be called before setting any
// attribute.
button->SetIsNativeAnonymousRoot();
button->SetPseudoElementType(PseudoStyleType::fileChooserButton);
button->SetPseudoElementType(PseudoStyleType::fileSelectorButton);
// Set the file picking button text depending on the current locale.
nsAutoString buttonTxt;
@ -282,10 +282,8 @@ nsresult nsFileControlFrame::CreateAnonymousContent(
aElements.AppendElement(mTextContent);
// We should be able to interact with the element by doing drag and drop.
mContent->AddSystemEventListener(NS_LITERAL_STRING("drop"), mMouseListener,
false);
mContent->AddSystemEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, false);
mContent->AddSystemEventListener(u"drop"_ns, mMouseListener, false);
mContent->AddSystemEventListener(u"dragover"_ns, mMouseListener, false);
SyncDisabledState();
@ -368,7 +366,7 @@ nsFileControlFrame::DnDListener::HandleEvent(Event* aEvent) {
bool supportsMultiple =
inputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) {
dataTransfer->SetDropEffect(NS_LITERAL_STRING("none"));
dataTransfer->SetDropEffect(u"none"_ns);
aEvent->StopPropagation();
return NS_OK;
}
@ -442,7 +440,7 @@ nsFileControlFrame::DnDListener::HandleEvent(Event* aEvent) {
"Failed to dispatch input event");
nsContentUtils::DispatchTrustedEvent(
inputElement->OwnerDoc(), static_cast<nsINode*>(inputElement),
NS_LITERAL_STRING("change"), CanBubble::eYes, Cancelable::eNo);
u"change"_ns, CanBubble::eYes, Cancelable::eNo);
}
}
@ -541,8 +539,8 @@ nscoord nsFileControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
void nsFileControlFrame::SyncDisabledState() {
EventStates eventStates = mContent->AsElement()->State();
if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
mBrowseFilesOrDirs->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
EmptyString(), true);
mBrowseFilesOrDirs->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, u""_ns,
true);
} else {
mBrowseFilesOrDirs->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true);
}
@ -572,7 +570,7 @@ void nsFileControlFrame::ContentStatesChanged(EventStates aStates) {
#ifdef DEBUG_FRAME_DUMP
nsresult nsFileControlFrame::GetFrameName(nsAString& aResult) const {
return MakeFrameName(NS_LITERAL_STRING("FileControl"), aResult);
return MakeFrameName(u"FileControl"_ns, aResult);
}
#endif

View File

@ -32,7 +32,7 @@ void nsGfxButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
#ifdef DEBUG_FRAME_DUMP
nsresult nsGfxButtonControlFrame::GetFrameName(nsAString& aResult) const {
return MakeFrameName(NS_LITERAL_STRING("ButtonControl"), aResult);
return MakeFrameName(u"ButtonControl"_ns, aResult);
}
#endif

View File

@ -131,7 +131,7 @@ nscoord nsHTMLButtonControlFrame::GetMinISize(gfxContext* aRenderingContext) {
} else {
nsIFrame* kid = mFrames.FirstChild();
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
nsLayoutUtils::MIN_ISIZE);
IntrinsicISizeType::MinISize);
}
return result;
}
@ -143,8 +143,8 @@ nscoord nsHTMLButtonControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
result = 0;
} else {
nsIFrame* kid = mFrames.FirstChild();
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
nsLayoutUtils::PREF_ISIZE);
result = nsLayoutUtils::IntrinsicForContainer(
aRenderingContext, kid, IntrinsicISizeType::PrefISize);
}
return result;
}
@ -174,7 +174,7 @@ void nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
// XXXbz Eventually we may want to check-and-bail if
// !aReflowInput.ShouldReflowAllKids() &&
// !NS_SUBTREE_DIRTY(firstKid).
// !firstKid->IsSubtreeDirty().
// We'd need to cache our ascent for that, of course.
// Reflow the contents of the button.
@ -206,7 +206,8 @@ void nsHTMLButtonControlFrame::ReflowButtonContents(
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
// shorthand for a value we need to use in a bunch of places
const LogicalMargin& clbp = aButtonReflowInput.ComputedLogicalBorderPadding();
const LogicalMargin& clbp =
aButtonReflowInput.ComputedLogicalBorderPadding(wm);
LogicalPoint childPos(wm);
childPos.I(wm) = clbp.IStart(wm);

View File

@ -72,7 +72,7 @@ class nsHTMLButtonControlFrame : public nsContainerFrame,
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("HTMLButtonControl"), aResult);
return MakeFrameName(u"HTMLButtonControl"_ns, aResult);
}
#endif

View File

@ -41,7 +41,7 @@ class nsImageControlFrame final : public nsImageFrame,
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const final {
return MakeFrameName(NS_LITERAL_STRING("ImageControl"), aResult);
return MakeFrameName(u"ImageControl"_ns, aResult);
}
#endif
@ -138,7 +138,8 @@ nsresult nsImageControlFrame::HandleEvent(nsPresContext* aPresContext,
mContent->GetProperty(nsGkAtoms::imageClickedPoint));
if (lastClickPoint) {
// normally lastClickedPoint is not null, as it's allocated in Init()
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(
aEvent, RelativeTo{this});
TranslateEventCoords(pt, *lastClickPoint);
}
}

View File

@ -1,91 +0,0 @@
/* 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/. */
#include "nsLegendFrame.h"
#include "mozilla/dom/HTMLLegendElement.h"
#include "mozilla/PresShell.h"
#include "ComputedStyle.h"
#include "nsIContent.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValueInlines.h"
#include "nsHTMLParts.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsCheckboxRadioFrame.h"
#include "WritingModes.h"
using namespace mozilla;
nsIFrame* NS_NewLegendFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
#ifdef DEBUG
const nsStyleDisplay* disp = aStyle->StyleDisplay();
NS_ASSERTION(!disp->IsAbsolutelyPositionedStyle() && !disp->IsFloatingStyle(),
"Legends should not be positioned and should not float");
#endif
nsIFrame* f =
new (aPresShell) nsLegendFrame(aStyle, aPresShell->GetPresContext());
f->AddStateBits(NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS);
return f;
}
NS_IMPL_FRAMEARENA_HELPERS(nsLegendFrame)
void nsLegendFrame::DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) {
nsCheckboxRadioFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
nsBlockFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}
NS_QUERYFRAME_HEAD(nsLegendFrame)
NS_QUERYFRAME_ENTRY(nsLegendFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
void nsLegendFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
DO_GLOBAL_REFLOW_COUNT("nsLegendFrame");
DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
if (mState & NS_FRAME_FIRST_REFLOW) {
nsCheckboxRadioFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
}
return nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowInput,
aStatus);
}
dom::HTMLLegendElement::LegendAlignValue nsLegendFrame::GetLogicalAlign(
WritingMode aCBWM) {
using LegendAlignValue = dom::HTMLLegendElement::LegendAlignValue;
auto* element = nsGenericHTMLElement::FromNode(mContent);
if (!element) {
return LegendAlignValue::InlineStart;
}
const nsAttrValue* attr = element->GetParsedAttr(nsGkAtoms::align);
if (!attr || attr->Type() != nsAttrValue::eEnum) {
return LegendAlignValue::InlineStart;
}
auto value = static_cast<LegendAlignValue>(attr->GetEnumValue());
switch (value) {
case LegendAlignValue::Left:
return aCBWM.IsBidiLTR() ? LegendAlignValue::InlineStart
: LegendAlignValue::InlineEnd;
case LegendAlignValue::Right:
return aCBWM.IsBidiLTR() ? LegendAlignValue::InlineEnd
: LegendAlignValue::InlineStart;
default:
return value;
}
}
#ifdef DEBUG_FRAME_DUMP
nsresult nsLegendFrame::GetFrameName(nsAString& aResult) const {
return MakeFrameName(NS_LITERAL_STRING("Legend"), aResult);
}
#endif

View File

@ -1,34 +0,0 @@
/* 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/. */
#ifndef nsLegendFrame_h___
#define nsLegendFrame_h___
#include "mozilla/Attributes.h"
#include "nsBlockFrame.h"
class nsLegendFrame final : public nsBlockFrame {
public:
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsLegendFrame)
explicit nsLegendFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
: nsBlockFrame(aStyle, aPresContext, kClassID) {}
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
HTMLLegendElement::LegendAlignValue GetLogicalAlign(
mozilla::WritingMode aCBWM);
};
#endif // guard

View File

@ -133,20 +133,15 @@ void nsListControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
mEventListener->SetFrame(nullptr);
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"),
mEventListener, false);
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("keypress"),
mEventListener, false);
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"),
mEventListener, false);
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mouseup"),
mEventListener, false);
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"),
mEventListener, false);
mContent->RemoveSystemEventListener(u"keydown"_ns, mEventListener, false);
mContent->RemoveSystemEventListener(u"keypress"_ns, mEventListener, false);
mContent->RemoveSystemEventListener(u"mousedown"_ns, mEventListener, false);
mContent->RemoveSystemEventListener(u"mouseup"_ns, mEventListener, false);
mContent->RemoveSystemEventListener(u"mousemove"_ns, mEventListener, false);
if (ShouldFireDropDownEvent()) {
nsContentUtils::AddScriptRunner(
new AsyncEventDispatcher(mContent, NS_LITERAL_STRING("mozhidedropdown"),
new AsyncEventDispatcher(mContent, u"mozhidedropdown"_ns,
CanBubble::eYes, ChromeOnlyDispatch::eYes));
}
@ -399,8 +394,8 @@ void nsListControlFrame::Reflow(nsPresContext* aPresContext,
bool autoBSize = (aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE);
mMightNeedSecondPass = autoBSize && (NS_SUBTREE_DIRTY(this) ||
aReflowInput.ShouldReflowAllKids());
mMightNeedSecondPass =
autoBSize && (IsSubtreeDirty() || aReflowInput.ShouldReflowAllKids());
ReflowInput state(aReflowInput);
int32_t length = GetNumberOfRows();
@ -482,8 +477,7 @@ void nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext,
MOZ_ASSERT(aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE,
"We should not have a computed block size here!");
mMightNeedSecondPass =
NS_SUBTREE_DIRTY(this) || aReflowInput.ShouldReflowAllKids();
mMightNeedSecondPass = IsSubtreeDirty() || aReflowInput.ShouldReflowAllKids();
WritingMode wm = aReflowInput.GetWritingMode();
#ifdef DEBUG
@ -565,7 +559,7 @@ void nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext,
mNumDisplayRows = 1;
mDropdownCanGrow = GetNumberOfRows() > 1;
} else {
nscoord bp = aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm);
nscoord bp = aReflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(wm);
nscoord availableBSize = std::max(before, after) - bp;
nscoord newBSize;
uint32_t rows;
@ -928,16 +922,14 @@ void nsListControlFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
// we need to hook up our listeners before the editor is initialized
mEventListener = new nsListEventListener(this);
mContent->AddSystemEventListener(NS_LITERAL_STRING("keydown"), mEventListener,
false, false);
mContent->AddSystemEventListener(NS_LITERAL_STRING("keypress"),
mEventListener, false, false);
mContent->AddSystemEventListener(NS_LITERAL_STRING("mousedown"),
mEventListener, false, false);
mContent->AddSystemEventListener(NS_LITERAL_STRING("mouseup"), mEventListener,
false, false);
mContent->AddSystemEventListener(NS_LITERAL_STRING("mousemove"),
mEventListener, false, false);
mContent->AddSystemEventListener(u"keydown"_ns, mEventListener, false, false);
mContent->AddSystemEventListener(u"keypress"_ns, mEventListener, false,
false);
mContent->AddSystemEventListener(u"mousedown"_ns, mEventListener, false,
false);
mContent->AddSystemEventListener(u"mouseup"_ns, mEventListener, false, false);
mContent->AddSystemEventListener(u"mousemove"_ns, mEventListener, false,
false);
mStartSelectionIndex = kNothingSelected;
mEndSelectionIndex = kNothingSelected;
@ -1025,7 +1017,7 @@ void nsListControlFrame::SetComboboxFrame(nsIFrame* aComboboxFrame) {
void nsListControlFrame::GetOptionText(uint32_t aIndex, nsAString& aStr) {
aStr.Truncate();
if (dom::HTMLOptionElement* optionElement = GetOption(aIndex)) {
optionElement->GetText(aStr);
optionElement->GetRenderedLabel(aStr);
}
}
@ -1290,8 +1282,8 @@ void nsListControlFrame::FireOnInputAndOnChange() {
// Dispatch the change event.
nsContentUtils::DispatchTrustedEvent(element->OwnerDoc(), element,
NS_LITERAL_STRING("change"),
CanBubble::eYes, Cancelable::eNo);
u"change"_ns, CanBubble::eYes,
Cancelable::eNo);
}
NS_IMETHODIMP_(void)
@ -1418,7 +1410,7 @@ void nsListControlFrame::DidReflow(nsPresContext* aPresContext,
#ifdef DEBUG_FRAME_DUMP
nsresult nsListControlFrame::GetFrameName(nsAString& aResult) const {
return MakeFrameName(NS_LITERAL_STRING("ListControl"), aResult);
return MakeFrameName(u"ListControl"_ns, aResult);
}
#endif
@ -1602,7 +1594,7 @@ void nsListControlFrame::FireMenuItemActiveEvent() {
return;
}
FireDOMEvent(NS_LITERAL_STRING("DOMMenuItemActive"), optionContent);
FireDOMEvent(u"DOMMenuItemActive"_ns, optionContent);
}
#endif
@ -1641,11 +1633,10 @@ static bool FireShowDropDownEvent(nsIContent* aContent, bool aShow,
if (ShouldFireDropDownEvent()) {
nsString eventName;
if (aShow) {
eventName = aIsSourceTouchEvent
? NS_LITERAL_STRING("mozshowdropdown-sourcetouch")
: NS_LITERAL_STRING("mozshowdropdown");
eventName = aIsSourceTouchEvent ? u"mozshowdropdown-sourcetouch"_ns
: u"mozshowdropdown"_ns;
} else {
eventName = NS_LITERAL_STRING("mozhidedropdown");
eventName = u"mozhidedropdown"_ns;
}
nsContentUtils::DispatchChromeEvent(aContent->OwnerDoc(), aContent,
eventName, CanBubble::eYes,
@ -2275,11 +2266,11 @@ nsresult nsListControlFrame::KeyPress(dom::Event* aKeyEvent) {
}
nsAutoString text;
optionElement->GetText(text);
optionElement->GetRenderedLabel(text);
if (!StringBeginsWith(
nsContentUtils::TrimWhitespace<
nsContentUtils::IsHTMLWhitespaceOrNBSP>(text, false),
incrementalString, nsCaseInsensitiveStringComparator())) {
incrementalString, nsCaseInsensitiveStringComparator)) {
continue;
}

View File

@ -97,8 +97,8 @@ void nsMeterFrame::Reflow(nsPresContext* aPresContext,
ReflowBarFrame(barFrame, aPresContext, aReflowInput, aStatus);
aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
aReflowInput.ComputedSizeWithBorderPadding());
const auto wm = aReflowInput.GetWritingMode();
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
aDesiredSize.SetOverflowAreasToDesiredBounds();
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
@ -185,7 +185,7 @@ nsresult nsMeterFrame::AttributeChanged(int32_t aNameSpaceID,
LogicalSize nsMeterFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorder, const LogicalSize& aPadding,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);

View File

@ -33,7 +33,7 @@ class nsMeterFrame final : public nsContainerFrame,
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("Meter"), aResult);
return MakeFrameName(u"Meter"_ns, aResult);
}
#endif
@ -49,8 +49,10 @@ class nsMeterFrame final : public nsContainerFrame,
virtual mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;

View File

@ -55,7 +55,7 @@ already_AddRefed<Element> nsNumberControlFrame::MakeAnonymousElement(
if (aPseudoType == PseudoStyleType::mozNumberSpinDown ||
aPseudoType == PseudoStyleType::mozNumberSpinUp) {
resultElement->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_hidden,
NS_LITERAL_STRING("true"), false);
u"true"_ns, false);
}
if (aParent) {
@ -194,7 +194,7 @@ int32_t nsNumberControlFrame::GetSpinButtonForPointerEvent(
// default UA style sheet. See the comment in forms.css for why.
LayoutDeviceIntPoint absPoint = aEvent->mRefPoint;
nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
aEvent, absPoint, mSpinBox->GetPrimaryFrame());
aEvent, absPoint, RelativeTo{mSpinBox->GetPrimaryFrame()});
if (point != nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
if (point.y < mSpinBox->GetPrimaryFrame()->GetSize().height / 2) {
return eSpinButtonUp;

View File

@ -60,7 +60,7 @@ class nsNumberControlFrame final : public nsTextControlFrame {
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("NumberControl"), aResult);
return MakeFrameName(u"NumberControl"_ns, aResult);
}
#endif

View File

@ -100,8 +100,8 @@ void nsProgressFrame::Reflow(nsPresContext* aPresContext,
nsCheckboxRadioFrame::RegUnRegAccessKey(this, true);
}
aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
aReflowInput.ComputedSizeWithBorderPadding());
const auto wm = aReflowInput.GetWritingMode();
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
aDesiredSize.SetOverflowAreasToDesiredBounds();
for (auto childFrame : PrincipalChildList()) {
@ -202,7 +202,7 @@ nsresult nsProgressFrame::AttributeChanged(int32_t aNameSpaceID,
LogicalSize nsProgressFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorder, const LogicalSize& aPadding,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
const WritingMode wm = GetWritingMode();
LogicalSize autoSize(wm);

View File

@ -38,7 +38,7 @@ class nsProgressFrame final : public nsContainerFrame,
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("Progress"), aResult);
return MakeFrameName(u"Progress"_ns, aResult);
}
#endif
@ -54,8 +54,10 @@ class nsProgressFrame final : public nsContainerFrame,
virtual mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;

View File

@ -67,8 +67,7 @@ void nsRangeFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
if (!mDummyTouchListener) {
mDummyTouchListener = new DummyTouchListener();
}
aContent->AddEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
aContent->AddEventListener(u"touchstart"_ns, mDummyTouchListener, false);
return nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
}
@ -79,8 +78,7 @@ void nsRangeFrame::DestroyFrom(nsIFrame* aDestructRoot,
"nsRangeFrame should not have continuations; if it does we "
"need to call RegUnregAccessKey only for the first.");
mContent->RemoveEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
mContent->RemoveEventListener(u"touchstart"_ns, mDummyTouchListener, false);
nsCheckboxRadioFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
aPostDestroyData.AddAnonymousContent(mTrackDiv.forget());
@ -188,12 +186,10 @@ void nsRangeFrame::Reflow(nsPresContext* aPresContext,
if (computedBSize == NS_UNCONSTRAINEDSIZE) {
computedBSize = 0;
}
const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(wm);
LogicalSize finalSize(
wm,
aReflowInput.ComputedISize() +
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm),
computedBSize +
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm));
wm, aReflowInput.ComputedISize() + borderPadding.IStartEnd(wm),
computedBSize + borderPadding.BStartEnd(wm));
aDesiredSize.SetSize(wm, finalSize);
ReflowAnonymousContent(aPresContext, aDesiredSize, aReflowInput);
@ -391,8 +387,8 @@ Decimal nsRangeFrame::GetValueAtEventPoint(WidgetGUIEvent* aEvent) {
} else {
absPoint = aEvent->mRefPoint;
}
nsPoint point =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, absPoint, this);
nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
aEvent, absPoint, RelativeTo{this});
if (point == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
// We don't want to change the current value for this error state.
@ -460,7 +456,7 @@ Decimal nsRangeFrame::GetValueAtEventPoint(WidgetGUIEvent* aEvent) {
}
void nsRangeFrame::UpdateForValueChange() {
if (NS_SUBTREE_DIRTY(this)) {
if (IsSubtreeDirty()) {
return; // we're going to be updated when we reflow
}
nsIFrame* rangeProgressFrame = mProgressDiv->GetPrimaryFrame();
@ -628,7 +624,7 @@ nscoord nsRangeFrame::AutoCrossSize(nscoord aEm) {
LogicalSize nsRangeFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorder, const LogicalSize& aPadding,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
bool isInlineOriented = IsInlineOriented();
auto em = StyleFont()->mFont.size * nsLayoutUtils::FontSizeInflationFor(this);

View File

@ -55,7 +55,7 @@ class nsRangeFrame final : public nsContainerFrame,
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("Range"), aResult);
return MakeFrameName(u"Range"_ns, aResult);
}
#endif
@ -72,11 +72,13 @@ class nsRangeFrame final : public nsContainerFrame,
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
virtual mozilla::LogicalSize ComputeAutoSize(
mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;

View File

@ -112,7 +112,7 @@ class nsDisplayListFocus : public nsPaintedDisplayItem {
// override bounds because the list item focus ring may extend outside
// the nsSelectsAreaFrame
nsListControlFrame* listFrame = GetEnclosingListFrame(Frame());
return listFrame->GetVisualOverflowRectRelativeToSelf() +
return listFrame->InkOverflowRectRelativeToSelf() +
listFrame->GetOffsetToCrossDoc(ReferenceFrame());
}
virtual void Paint(nsDisplayListBuilder* aBuilder,

View File

@ -9,6 +9,7 @@
#include "nsFontMetrics.h"
#include "nsTextControlFrame.h"
#include "nsIEditor.h"
#include "nsIScrollableFrame.h"
#include "nsCaret.h"
#include "nsCSSPseudoElements.h"
#include "nsGenericHTMLElement.h"
@ -123,7 +124,7 @@ nsTextControlFrame::nsTextControlFrame(ComputedStyle* aStyle,
nsTextControlFrame::~nsTextControlFrame() = default;
nsIScrollableFrame* nsTextControlFrame::GetScrollTargetFrame() {
nsIScrollableFrame* nsTextControlFrame::GetScrollTargetFrame() const {
if (!mRootNode) {
return nullptr;
}
@ -530,30 +531,32 @@ nscoord nsTextControlFrame::GetMinISize(gfxContext* aRenderingContext) {
LogicalSize nsTextControlFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorder, const LogicalSize& aPadding,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
LogicalSize autoSize = CalcIntrinsicSize(aRenderingContext, aWM, inflation);
// Note: nsContainerFrame::ComputeAutoSize only computes the inline-size (and
// only for 'auto'), the block-size it returns is always NS_UNCONSTRAINEDSIZE.
const auto& iSizeCoord = StylePosition()->ISize(aWM);
if (iSizeCoord.IsAuto()) {
if (aFlags & ComputeSizeFlags::eIClampMarginBoxMinSize) {
const auto& styleISize = aSizeOverrides.mStyleISize
? *aSizeOverrides.mStyleISize
: StylePosition()->ISize(aWM);
if (styleISize.IsAuto()) {
if (aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize)) {
// CalcIntrinsicSize isn't aware of grid-item margin-box clamping, so we
// fall back to nsContainerFrame's ComputeAutoSize to handle that.
// XXX maybe a font-inflation issue here? (per the assertion below).
autoSize.ISize(aWM) =
nsContainerFrame::ComputeAutoSize(aRenderingContext, aWM, aCBSize,
aAvailableISize, aMargin, aBorder,
aPadding, aFlags)
nsContainerFrame::ComputeAutoSize(
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin,
aBorderPadding, aSizeOverrides, aFlags)
.ISize(aWM);
}
#ifdef DEBUG
else {
LogicalSize ancestorAutoSize = nsContainerFrame::ComputeAutoSize(
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin, aBorder,
aPadding, aFlags);
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin,
aBorderPadding, aSizeOverrides, aFlags);
// Disabled when there's inflation; see comment in GetXULPrefSize.
MOZ_ASSERT(inflation != 1.0f ||
ancestorAutoSize.ISize(aWM) == autoSize.ISize(aWM),
@ -584,7 +587,7 @@ void nsTextControlFrame::ComputeBaseline(const ReflowInput& aReflowInput,
nsLayoutUtils::GetFontMetricsForFrame(this, inflation);
mFirstBaseline = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight,
wm.IsLineInverted()) +
aReflowInput.ComputedLogicalBorderPadding().BStart(wm);
aReflowInput.ComputedLogicalBorderPadding(wm).BStart(wm);
aDesiredSize.SetBlockStartAscent(mFirstBaseline);
}
@ -604,13 +607,7 @@ void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
// set values of reflow's out parameters
WritingMode wm = aReflowInput.GetWritingMode();
LogicalSize finalSize(
wm,
aReflowInput.ComputedISize() +
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm),
aReflowInput.ComputedBSize() +
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm));
aDesiredSize.SetSize(wm, finalSize);
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
ComputeBaseline(aReflowInput, aDesiredSize);
@ -641,11 +638,11 @@ void nsTextControlFrame::ReflowTextControlChild(
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput kidReflowInput(aPresContext, aReflowInput, aKid, availSize,
Nothing(), ReflowInput::CALLER_WILL_INIT);
Nothing(), ReflowInput::InitFlag::CallerWillInit);
// Override padding with our computed padding in case we got it from theming
// or percentage.
kidReflowInput.Init(aPresContext, Nothing(), nullptr,
&aReflowInput.ComputedPhysicalPadding());
kidReflowInput.Init(aPresContext, Nothing(), Nothing(),
Some(aReflowInput.ComputedLogicalPadding(wm)));
// Set computed width and computed height for the child
kidReflowInput.SetComputedWidth(aReflowInput.ComputedWidth());

View File

@ -57,10 +57,7 @@ class nsTextControlFrame : public nsContainerFrame,
MOZ_CAN_RUN_SCRIPT_BOUNDARY void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData&) override;
nsIScrollableFrame* GetScrollTargetFrame() override;
nsIScrollableFrame* GetScrollTargetFrame() const {
return const_cast<nsTextControlFrame*>(this)->GetScrollTargetFrame();
}
nsIScrollableFrame* GetScrollTargetFrame() const override;
nscoord GetMinISize(gfxContext* aRenderingContext) override;
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
@ -68,8 +65,10 @@ class nsTextControlFrame : public nsContainerFrame,
mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,

View File

@ -0,0 +1,30 @@
/* 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/. */
#include "AspectRatio.h"
#include "mozilla/WritingModes.h"
namespace mozilla {
nscoord AspectRatio::ComputeRatioDependentSize(
LogicalAxis aRatioDependentAxis, const WritingMode& aWM,
nscoord aRatioDeterminingSize,
const LogicalSize& aContentBoxSizeToBoxSizingAdjust) const {
MOZ_ASSERT(*this,
"Infinite or zero ratio may have undefined behavior when "
"computing the size");
const LogicalSize& boxSizingAdjust = mUseBoxSizing == UseBoxSizing::No
? LogicalSize(aWM)
: aContentBoxSizeToBoxSizingAdjust;
return aRatioDependentAxis == LogicalAxis::eLogicalAxisInline
? ConvertToWritingMode(aWM).ApplyTo(aRatioDeterminingSize +
boxSizingAdjust.BSize(aWM)) -
boxSizingAdjust.ISize(aWM)
: ConvertToWritingMode(aWM).Inverted().ApplyTo(
aRatioDeterminingSize + boxSizingAdjust.ISize(aWM)) -
boxSizingAdjust.BSize(aWM);
}
} // namespace mozilla

View File

@ -8,21 +8,49 @@
/* The aspect ratio of a box, in a "width / height" format. */
#include "mozilla/Attributes.h"
#include "mozilla/gfx/BaseSize.h"
#include "nsCoord.h"
#include <algorithm>
#include <limits>
namespace IPC {
template <typename T>
struct ParamTraits;
} // namespace IPC
namespace mozilla {
struct AspectRatio {
AspectRatio() : mRatio(0.0f) {}
explicit AspectRatio(float aRatio) : mRatio(std::max(aRatio, 0.0f)) {}
enum LogicalAxis : uint8_t;
class LogicalSize;
class WritingMode;
static AspectRatio FromSize(float aWidth, float aHeight) {
enum class UseBoxSizing : uint8_t {
// The aspect ratio works with content box dimensions always.
No,
// The aspect ratio works with the dimensions of the box specified by
// box-sizing.
Yes,
};
struct AspectRatio {
AspectRatio() = default;
explicit AspectRatio(float aRatio,
UseBoxSizing aUseBoxSizing = UseBoxSizing::No)
: mRatio(std::max(aRatio, 0.0f)), mUseBoxSizing(aUseBoxSizing) {}
static AspectRatio FromSize(float aWidth, float aHeight,
UseBoxSizing aUseBoxSizing = UseBoxSizing::No) {
if (aWidth == 0.0f || aHeight == 0.0f) {
// For the degenerate ratio, we don't care about which box sizing we are
// using, so using default constructor is fine.
return AspectRatio();
}
return AspectRatio(aWidth / aHeight);
return AspectRatio(aWidth / aHeight, aUseBoxSizing);
}
template <typename T, typename Sub>
static AspectRatio FromSize(const gfx::BaseSize<T, Sub>& aSize) {
return FromSize(aSize.Width(), aSize.Height());
}
explicit operator bool() const { return mRatio != 0.0f; }
@ -46,11 +74,51 @@ struct AspectRatio {
// 0.0f in the division here (so that valid ratios always generate other
// valid ratios when inverted).
return AspectRatio(
std::max(std::numeric_limits<float>::epsilon(), 1.0f / mRatio));
std::max(std::numeric_limits<float>::epsilon(), 1.0f / mRatio),
mUseBoxSizing);
}
[[nodiscard]] inline AspectRatio ConvertToWritingMode(
const WritingMode& aWM) const;
/**
* This method computes the ratio-dependent size by the ratio-determining size
* and aspect-ratio (i.e. preferred aspect ratio). Basically this function
* will be used in the calculation of 'auto' sizes when the preferred
* aspect ratio is not 'auto'.
*
* @param aRatioDependentAxis The ratio depenedent axis of the box.
* @param aWM The writing mode of the box.
* @param aRatioDetermingSize The content-box size on the ratio determining
* axis. Basically, we use this size and |mRatio|
* to compute the size on the ratio-dependent
* axis.
* @param aContentBoxSizeToBoxSizingAdjust The border padding box size
* adjustment. We need this because
* aspect-ratio should take the
* box-sizing into account if its
* style is '<ratio>'. If its style
* is 'auto & <ratio>', we should use
* content-box dimensions always.
* If the callers want the ratio to
* apply to the content-box size, we
* should pass a zero LogicalSize.
* If mUseBoxSizing is No, we ignore
* this parameter because we should
* use content box dimensions always.
*
* The return value is the content-box size on the ratio-dependent axis.
* Plese see the definition of the ratio-dependent axis and the
* ratio-determining axis in the spec:
* https://drafts.csswg.org/css-sizing-4/#aspect-ratio
*/
[[nodiscard]] nscoord ComputeRatioDependentSize(
LogicalAxis aRatioDependentAxis, const WritingMode& aWM,
nscoord aRatioDeterminingSize,
const LogicalSize& aContentBoxSizeToBoxSizingAdjust) const;
bool operator==(const AspectRatio& aOther) const {
return mRatio == aOther.mRatio;
return mRatio == aOther.mRatio && mUseBoxSizing == aOther.mUseBoxSizing;
}
bool operator!=(const AspectRatio& aOther) const {
@ -58,12 +126,16 @@ struct AspectRatio {
}
bool operator<(const AspectRatio& aOther) const {
MOZ_ASSERT(
mUseBoxSizing == aOther.mUseBoxSizing,
"Do not compare AspectRatio if their mUseBoxSizing are different.");
return mRatio < aOther.mRatio;
}
private:
// 0.0f represents no aspect ratio.
float mRatio;
float mRatio = 0.0f;
UseBoxSizing mUseBoxSizing = UseBoxSizing::No;
};
} // namespace mozilla

Some files were not shown because too many files have changed in this diff Show More