mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 14:55:44 -04:00
68.14.6 - layout - servo
This commit is contained in:
parent
241983a236
commit
d3ff103fd5
@ -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());
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
1054
layout/base/DisplayPortUtils.cpp
Normal file
1054
layout/base/DisplayPortUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
314
layout/base/DisplayPortUtils.h
Normal file
314
layout/base/DisplayPortUtils.h
Normal 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__
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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___
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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(), ¤tBorder, ¤tPadding);
|
||||
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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
49
layout/base/RelativeTo.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsMargin.h"
|
||||
#include "nsStyleStruct.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "mozilla/SVGContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
100
layout/base/SurfaceFromElementResult.h
Normal file
100
layout/base/SurfaceFromElementResult.h
Normal 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
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
225
layout/base/ViewportUtils.cpp
Normal file
225
layout/base/ViewportUtils.cpp
Normal 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
110
layout/base/ViewportUtils.h
Normal 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 */
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
11
layout/base/crashtests/1422908.html
Normal file
11
layout/base/crashtests/1422908.html
Normal 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">
|
7
layout/base/crashtests/1690163.html
Normal file
7
layout/base/crashtests/1690163.html
Normal file
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
window.onload = () => {
|
||||
document.getElementById('a').appendChild(document.createElement('col'))
|
||||
}
|
||||
</script>
|
||||
<fieldset id='a'>
|
||||
<legend>
|
@ -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
|
||||
|
@ -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/',
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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; \
|
||||
|
@ -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
@ -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(
|
||||
|
@ -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, ®ion);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]:
|
||||
//
|
||||
|
65
layout/base/nsRefreshObservers.h
Normal file
65
layout/base/nsRefreshObservers.h
Normal 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
|
@ -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() {
|
||||
|
27
layout/base/tests/bug1670531-1.html
Normal file
27
layout/base/tests/bug1670531-1.html
Normal 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>
|
27
layout/base/tests/bug1670531-2.html
Normal file
27
layout/base/tests/bug1670531-2.html
Normal 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>
|
27
layout/base/tests/bug1670531-3-ref.html
Normal file
27
layout/base/tests/bug1670531-3-ref.html
Normal 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>
|
27
layout/base/tests/bug1670531-3.html
Normal file
27
layout/base/tests/bug1670531-3.html
Normal 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>
|
27
layout/base/tests/bug1670531-4.html
Normal file
27
layout/base/tests/bug1670531-4.html
Normal 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>
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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' ] ,
|
||||
|
@ -39,7 +39,6 @@ LOCAL_INCLUDES += [
|
||||
'/dom/media',
|
||||
'/dom/offline',
|
||||
'/dom/storage',
|
||||
'/dom/svg',
|
||||
'/dom/xbl',
|
||||
'/dom/xslt/base',
|
||||
'/dom/xslt/xml',
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
8
layout/forms/crashtests/1679471.html
Normal file
8
layout/forms/crashtests/1679471.html
Normal file
@ -0,0 +1,8 @@
|
||||
<style>
|
||||
* {
|
||||
rotate: 0.8339rad;
|
||||
inset: 84pt -15742cm 8% ! important;
|
||||
position: fixed;
|
||||
}
|
||||
</style>
|
||||
<button>
|
@ -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
|
||||
|
@ -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"]
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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,
|
||||
|
30
layout/generic/AspectRatio.cpp
Normal file
30
layout/generic/AspectRatio.cpp
Normal 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
|
@ -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
Loading…
Reference in New Issue
Block a user