mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 23:05:40 -04:00
68.14.6 - layout - servo
This commit is contained in:
parent
241983a236
commit
d3ff103fd5
@ -14,6 +14,7 @@
|
|||||||
#include "nsCSSFrameConstructor.h"
|
#include "nsCSSFrameConstructor.h"
|
||||||
#include "nsDOMTokenList.h"
|
#include "nsDOMTokenList.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsPlaceholderFrame.h"
|
#include "nsPlaceholderFrame.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -29,8 +30,9 @@ using namespace dom;
|
|||||||
|
|
||||||
NS_IMPL_ISUPPORTS(AccessibleCaret::DummyTouchListener, nsIDOMEventListener)
|
NS_IMPL_ISUPPORTS(AccessibleCaret::DummyTouchListener, nsIDOMEventListener)
|
||||||
|
|
||||||
NS_NAMED_LITERAL_STRING(AccessibleCaret::sTextOverlayElementId, "text-overlay");
|
const nsLiteralString AccessibleCaret::sTextOverlayElementId =
|
||||||
NS_NAMED_LITERAL_STRING(AccessibleCaret::sCaretImageElementId, "image");
|
u"text-overlay"_ns;
|
||||||
|
const nsLiteralString AccessibleCaret::sCaretImageElementId = u"image"_ns;
|
||||||
|
|
||||||
#define AC_PROCESS_ENUM_TO_STREAM(e) \
|
#define AC_PROCESS_ENUM_TO_STREAM(e) \
|
||||||
case (e): \
|
case (e): \
|
||||||
@ -111,16 +113,16 @@ nsAutoString AccessibleCaret::AppearanceString(Appearance aAppearance) {
|
|||||||
switch (aAppearance) {
|
switch (aAppearance) {
|
||||||
case Appearance::None:
|
case Appearance::None:
|
||||||
case Appearance::NormalNotShown:
|
case Appearance::NormalNotShown:
|
||||||
string = NS_LITERAL_STRING("none");
|
string = u"none"_ns;
|
||||||
break;
|
break;
|
||||||
case Appearance::Normal:
|
case Appearance::Normal:
|
||||||
string = NS_LITERAL_STRING("normal");
|
string = u"normal"_ns;
|
||||||
break;
|
break;
|
||||||
case Appearance::Right:
|
case Appearance::Right:
|
||||||
string = NS_LITERAL_STRING("right");
|
string = u"right"_ns;
|
||||||
break;
|
break;
|
||||||
case Appearance::Left:
|
case Appearance::Left:
|
||||||
string = NS_LITERAL_STRING("left");
|
string = u"left"_ns;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return string;
|
return string;
|
||||||
@ -165,8 +167,8 @@ void AccessibleCaret::EnsureApzAware() {
|
|||||||
// the element already.
|
// the element already.
|
||||||
if (!CaretElement().IsApzAware()) {
|
if (!CaretElement().IsApzAware()) {
|
||||||
// FIXME(emilio): Is this needed anymore?
|
// FIXME(emilio): Is this needed anymore?
|
||||||
CaretElement().AddEventListener(NS_LITERAL_STRING("touchstart"),
|
CaretElement().AddEventListener(u"touchstart"_ns, mDummyTouchListener,
|
||||||
mDummyTouchListener, false);
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,8 +206,8 @@ already_AddRefed<Element> AccessibleCaret::CreateCaretElement(
|
|||||||
|
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
RefPtr<Element> parent = aDocument->CreateHTMLElement(nsGkAtoms::div);
|
RefPtr<Element> parent = aDocument->CreateHTMLElement(nsGkAtoms::div);
|
||||||
parent->ClassList()->Add(NS_LITERAL_STRING("moz-accessiblecaret"), rv);
|
parent->ClassList()->Add(u"moz-accessiblecaret"_ns, rv);
|
||||||
parent->ClassList()->Add(NS_LITERAL_STRING("none"), rv);
|
parent->ClassList()->Add(u"none"_ns, rv);
|
||||||
|
|
||||||
auto CreateAndAppendChildElement =
|
auto CreateAndAppendChildElement =
|
||||||
[aDocument, &parent](const nsLiteralString& aElementId) {
|
[aDocument, &parent](const nsLiteralString& aElementId) {
|
||||||
@ -221,8 +223,8 @@ already_AddRefed<Element> AccessibleCaret::CreateCaretElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AccessibleCaret::RemoveCaretElement(Document* aDocument) {
|
void AccessibleCaret::RemoveCaretElement(Document* aDocument) {
|
||||||
CaretElement().RemoveEventListener(NS_LITERAL_STRING("touchstart"),
|
CaretElement().RemoveEventListener(u"touchstart"_ns, mDummyTouchListener,
|
||||||
mDummyTouchListener, false);
|
false);
|
||||||
|
|
||||||
aDocument->RemoveAnonymousContent(*mCaretElementHolder, IgnoreErrors());
|
aDocument->RemoveAnonymousContent(*mCaretElementHolder, IgnoreErrors());
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIDOMEventListener.h"
|
#include "nsIDOMEventListener.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h" // for WeakFrame only
|
||||||
#include "nsISupportsBase.h"
|
#include "nsISupportsBase.h"
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "nsLiteralString.h"
|
#include "nsLiteralString.h"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "nsFocusManager.h"
|
#include "nsFocusManager.h"
|
||||||
#include "nsFrameSelection.h"
|
#include "nsFrameSelection.h"
|
||||||
#include "nsITimer.h"
|
#include "nsITimer.h"
|
||||||
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
@ -686,8 +687,8 @@ nsPoint AccessibleCaretEventHub::GetTouchEventPosition(
|
|||||||
|
|
||||||
// Get event coordinate relative to root frame.
|
// Get event coordinate relative to root frame.
|
||||||
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
||||||
return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, touchIntPoint,
|
return nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
||||||
rootFrame);
|
aEvent, touchIntPoint, RelativeTo{rootFrame});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||||
@ -700,7 +701,7 @@ nsPoint AccessibleCaretEventHub::GetMouseEventPosition(
|
|||||||
// Get event coordinate relative to root frame.
|
// Get event coordinate relative to root frame.
|
||||||
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
||||||
return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, mouseIntPoint,
|
return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, mouseIntPoint,
|
||||||
rootFrame);
|
RelativeTo{rootFrame});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
#ifndef mozilla_AccessibleCaretEventHub_h
|
#ifndef mozilla_AccessibleCaretEventHub_h
|
||||||
#define mozilla_AccessibleCaretEventHub_h
|
#define mozilla_AccessibleCaretEventHub_h
|
||||||
|
|
||||||
|
#include "LayoutConstants.h"
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/WeakPtr.h"
|
#include "mozilla/WeakPtr.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsDocShell.h"
|
#include "nsDocShell.h"
|
||||||
#include "nsIFrame.h"
|
|
||||||
#include "nsIReflowObserver.h"
|
#include "nsIReflowObserver.h"
|
||||||
#include "nsIScrollObserver.h"
|
#include "nsIScrollObserver.h"
|
||||||
#include "nsPoint.h"
|
#include "nsPoint.h"
|
||||||
|
@ -517,11 +517,6 @@ static EnumSet<nsLayoutUtils::FrameForPointOption> GetHitTestOptions() {
|
|||||||
EnumSet<nsLayoutUtils::FrameForPointOption> options = {
|
EnumSet<nsLayoutUtils::FrameForPointOption> options = {
|
||||||
nsLayoutUtils::FrameForPointOption::IgnorePaintSuppression,
|
nsLayoutUtils::FrameForPointOption::IgnorePaintSuppression,
|
||||||
nsLayoutUtils::FrameForPointOption::IgnoreCrossDoc};
|
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;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,8 +542,8 @@ nsresult AccessibleCaretManager::SelectWordOrShortcut(const nsPoint& aPoint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the frame under point.
|
// Find the frame under point.
|
||||||
AutoWeakFrame ptFrame =
|
AutoWeakFrame ptFrame = nsLayoutUtils::GetFrameForPoint(
|
||||||
nsLayoutUtils::GetFrameForPoint(rootFrame, aPoint, GetHitTestOptions());
|
RelativeTo{rootFrame}, aPoint, GetHitTestOptions());
|
||||||
if (!ptFrame.GetFrame()) {
|
if (!ptFrame.GetFrame()) {
|
||||||
return NS_ERROR_FAILURE;
|
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
|
// something under the original point will be selected, which may not be the
|
||||||
// original text the user wants to select.
|
// original text the user wants to select.
|
||||||
nsPoint ptInFrame = aPoint;
|
nsPoint ptInFrame = aPoint;
|
||||||
nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame);
|
nsLayoutUtils::TransformPoint(RelativeTo{rootFrame}, RelativeTo{ptFrame},
|
||||||
|
ptInFrame);
|
||||||
|
|
||||||
// Firstly check long press on an empty editable content.
|
// Firstly check long press on an empty editable content.
|
||||||
Element* newFocusEditingHost = GetEditingHostForFrame(ptFrame);
|
Element* newFocusEditingHost = GetEditingHostForFrame(ptFrame);
|
||||||
@ -927,8 +923,7 @@ void AccessibleCaretManager::SetSelectionDragState(bool aState) const {
|
|||||||
|
|
||||||
bool AccessibleCaretManager::IsPhoneNumber(nsAString& aCandidate) const {
|
bool AccessibleCaretManager::IsPhoneNumber(nsAString& aCandidate) const {
|
||||||
RefPtr<Document> doc = mPresShell->GetDocument();
|
RefPtr<Document> doc = mPresShell->GetDocument();
|
||||||
nsAutoString phoneNumberRegex(
|
nsAutoString phoneNumberRegex(u"(^\\+)?[0-9 ,\\-.()*#pw]{1,30}$"_ns);
|
||||||
NS_LITERAL_STRING("(^\\+)?[0-9 ,\\-.()*#pw]{1,30}$"));
|
|
||||||
return nsContentUtils::IsPatternMatching(aCandidate, phoneNumberRegex, doc)
|
return nsContentUtils::IsPatternMatching(aCandidate, phoneNumberRegex, doc)
|
||||||
.valueOr(false);
|
.valueOr(false);
|
||||||
}
|
}
|
||||||
@ -938,10 +933,10 @@ void AccessibleCaretManager::SelectMoreIfPhoneNumber() const {
|
|||||||
|
|
||||||
if (IsPhoneNumber(selectedText)) {
|
if (IsPhoneNumber(selectedText)) {
|
||||||
SetSelectionDirection(eDirNext);
|
SetSelectionDirection(eDirNext);
|
||||||
ExtendPhoneNumberSelection(NS_LITERAL_STRING("forward"));
|
ExtendPhoneNumberSelection(u"forward"_ns);
|
||||||
|
|
||||||
SetSelectionDirection(eDirPrevious);
|
SetSelectionDirection(eDirPrevious);
|
||||||
ExtendPhoneNumberSelection(NS_LITERAL_STRING("backward"));
|
ExtendPhoneNumberSelection(u"backward"_ns);
|
||||||
|
|
||||||
SetSelectionDirection(eDirNext);
|
SetSelectionDirection(eDirNext);
|
||||||
}
|
}
|
||||||
@ -973,8 +968,8 @@ void AccessibleCaretManager::ExtendPhoneNumberSelection(
|
|||||||
nsAutoString oldSelectedText = StringifiedSelection();
|
nsAutoString oldSelectedText = StringifiedSelection();
|
||||||
|
|
||||||
// Extend the selection by one char.
|
// Extend the selection by one char.
|
||||||
selection->Modify(NS_LITERAL_STRING("extend"), aDirection,
|
selection->Modify(u"extend"_ns, aDirection, u"character"_ns,
|
||||||
NS_LITERAL_STRING("character"), IgnoreErrors());
|
IgnoreErrors());
|
||||||
if (IsTerminated()) {
|
if (IsTerminated()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1218,8 +1213,8 @@ nsresult AccessibleCaretManager::DragCaretInternal(const nsPoint& aPoint) {
|
|||||||
|
|
||||||
// Find out which content we point to
|
// Find out which content we point to
|
||||||
|
|
||||||
nsIFrame* ptFrame =
|
nsIFrame* ptFrame = nsLayoutUtils::GetFrameForPoint(
|
||||||
nsLayoutUtils::GetFrameForPoint(rootFrame, point, GetHitTestOptions());
|
RelativeTo{rootFrame}, point, GetHitTestOptions());
|
||||||
if (!ptFrame) {
|
if (!ptFrame) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
@ -1231,7 +1226,8 @@ nsresult AccessibleCaretManager::DragCaretInternal(const nsPoint& aPoint) {
|
|||||||
nsIFrame* newFrame = nullptr;
|
nsIFrame* newFrame = nullptr;
|
||||||
nsPoint newPoint;
|
nsPoint newPoint;
|
||||||
nsPoint ptInFrame = point;
|
nsPoint ptInFrame = point;
|
||||||
nsLayoutUtils::TransformPoint(rootFrame, ptFrame, ptInFrame);
|
nsLayoutUtils::TransformPoint(RelativeTo{rootFrame}, RelativeTo{ptFrame},
|
||||||
|
ptInFrame);
|
||||||
result = fs->ConstrainFrameAndPointToAnchorSubtree(ptFrame, ptInFrame,
|
result = fs->ConstrainFrameAndPointToAnchorSubtree(ptFrame, ptInFrame,
|
||||||
&newFrame, newPoint);
|
&newFrame, newPoint);
|
||||||
if (NS_FAILED(result) || !newFrame) {
|
if (NS_FAILED(result) || !newFrame) {
|
||||||
@ -1277,7 +1273,7 @@ nsRect AccessibleCaretManager::GetAllChildFrameRectsUnion(
|
|||||||
for (const auto& childList : frame->ChildLists()) {
|
for (const auto& childList : frame->ChildLists()) {
|
||||||
// Loop all children to union their scrollable overflow rect.
|
// Loop all children to union their scrollable overflow rect.
|
||||||
for (nsIFrame* child : childList.mList) {
|
for (nsIFrame* child : childList.mList) {
|
||||||
nsRect childRect = child->GetScrollableOverflowRectRelativeToSelf();
|
nsRect childRect = child->ScrollableOverflowRectRelativeToSelf();
|
||||||
nsLayoutUtils::TransformRect(child, frame, childRect);
|
nsLayoutUtils::TransformRect(child, frame, childRect);
|
||||||
|
|
||||||
// A TextFrame containing only '\n' has positive height and width 0, or
|
// A TextFrame containing only '\n' has positive height and width 0, or
|
||||||
@ -1379,7 +1375,8 @@ void AccessibleCaretManager::StartSelectionAutoScrollTimer(
|
|||||||
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
nsIFrame* rootFrame = mPresShell->GetRootFrame();
|
||||||
MOZ_ASSERT(rootFrame);
|
MOZ_ASSERT(rootFrame);
|
||||||
nsPoint ptInScrolled = aPoint;
|
nsPoint ptInScrolled = aPoint;
|
||||||
nsLayoutUtils::TransformPoint(rootFrame, capturingFrame, ptInScrolled);
|
nsLayoutUtils::TransformPoint(RelativeTo{rootFrame},
|
||||||
|
RelativeTo{capturingFrame}, ptInScrolled);
|
||||||
|
|
||||||
RefPtr<nsFrameSelection> fs = GetFrameSelection();
|
RefPtr<nsFrameSelection> fs = GetFrameSelection();
|
||||||
MOZ_ASSERT(fs);
|
MOZ_ASSERT(fs);
|
||||||
@ -1463,7 +1460,7 @@ void AccessibleCaretManager::DispatchCaretStateChangedEvent(
|
|||||||
init.mSelectedTextContent = StringifiedSelection();
|
init.mSelectedTextContent = StringifiedSelection();
|
||||||
|
|
||||||
RefPtr<CaretStateChangedEvent> event = CaretStateChangedEvent::Constructor(
|
RefPtr<CaretStateChangedEvent> event = CaretStateChangedEvent::Constructor(
|
||||||
doc, NS_LITERAL_STRING("mozcaretstatechanged"), init);
|
doc, u"mozcaretstatechanged"_ns, init);
|
||||||
|
|
||||||
event->SetTrusted(true);
|
event->SetTrusted(true);
|
||||||
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = 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/DebugOnly.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/TypeTraits.h"
|
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
#include "GeckoMVMContext.h"
|
#include "GeckoMVMContext.h"
|
||||||
|
|
||||||
|
#include "mozilla/DisplayPortUtils.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
|
#include "mozilla/dom/VisualViewport.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsGlobalWindowInner.h"
|
#include "nsGlobalWindowInner.h"
|
||||||
#include "nsIDOMEventListener.h"
|
#include "nsIDOMEventListener.h"
|
||||||
@ -131,7 +133,7 @@ bool GeckoMVMContext::IsInReaderMode() const {
|
|||||||
if (NS_FAILED(mDocument->GetDocumentURI(uri))) {
|
if (NS_FAILED(mDocument->GetDocumentURI(uri))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static auto readerModeUriPrefix = NS_LITERAL_STRING("about:reader");
|
static auto readerModeUriPrefix = u"about:reader"_ns;
|
||||||
return StringBeginsWith(uri, readerModeUriPrefix);
|
return StringBeginsWith(uri, readerModeUriPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +156,7 @@ void GeckoMVMContext::SetVisualViewportSize(const CSSSize& aSize) {
|
|||||||
void GeckoMVMContext::UpdateDisplayPortMargins() {
|
void GeckoMVMContext::UpdateDisplayPortMargins() {
|
||||||
MOZ_ASSERT(mPresShell);
|
MOZ_ASSERT(mPresShell);
|
||||||
if (nsIFrame* root = mPresShell->GetRootScrollFrame()) {
|
if (nsIFrame* root = mPresShell->GetRootScrollFrame()) {
|
||||||
bool hasDisplayPort = nsLayoutUtils::HasDisplayPort(root->GetContent());
|
bool hasDisplayPort = DisplayPortUtils::HasDisplayPort(root->GetContent());
|
||||||
bool hasResolution = mPresShell->GetResolution() != 1.0f;
|
bool hasResolution = mPresShell->GetResolution() != 1.0f;
|
||||||
if (!hasDisplayPort && !hasResolution) {
|
if (!hasDisplayPort && !hasResolution) {
|
||||||
// We only want to update the displayport if there is one already, or
|
// 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
|
// ever changes we'd need to limit the size of this displayport base rect
|
||||||
// because non-toplevel documents have no limit on their size.
|
// because non-toplevel documents have no limit on their size.
|
||||||
MOZ_ASSERT(mPresShell->GetPresContext()->IsRootContentDocument());
|
MOZ_ASSERT(mPresShell->GetPresContext()->IsRootContentDocument());
|
||||||
nsLayoutUtils::SetDisplayPortBaseIfNotSet(root->GetContent(),
|
DisplayPortUtils::SetDisplayPortBaseIfNotSet(root->GetContent(),
|
||||||
displayportBase);
|
displayportBase);
|
||||||
nsIScrollableFrame* scrollable = do_QueryFrame(root);
|
nsIScrollableFrame* scrollable = do_QueryFrame(root);
|
||||||
nsLayoutUtils::CalculateAndSetDisplayPortMargins(
|
DisplayPortUtils::CalculateAndSetDisplayPortMargins(
|
||||||
scrollable, nsLayoutUtils::RepaintMode::Repaint);
|
scrollable, DisplayPortUtils::RepaintMode::Repaint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "GeometryUtils.h"
|
#include "GeometryUtils.h"
|
||||||
|
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/SVGUtils.h"
|
||||||
#include "mozilla/dom/CharacterData.h"
|
#include "mozilla/dom/CharacterData.h"
|
||||||
#include "mozilla/dom/DOMPointBinding.h"
|
#include "mozilla/dom/DOMPointBinding.h"
|
||||||
#include "mozilla/dom/GeometryUtilsBinding.h"
|
#include "mozilla/dom/GeometryUtilsBinding.h"
|
||||||
@ -16,7 +17,6 @@
|
|||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsCSSFrameConstructor.h"
|
#include "nsCSSFrameConstructor.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsSVGUtils.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
@ -140,7 +140,7 @@ static nsIFrame* GetFirstNonAnonymousFrameForNode(nsINode* aNode) {
|
|||||||
*/
|
*/
|
||||||
static nsRect GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType) {
|
static nsRect GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType) {
|
||||||
nsRect r;
|
nsRect r;
|
||||||
nsIFrame* f = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(*aFrame, &r);
|
nsIFrame* f = SVGUtils::GetOuterSVGFrameAndCoveredRegion(*aFrame, &r);
|
||||||
if (f && f != *aFrame) {
|
if (f && f != *aFrame) {
|
||||||
// For non-outer SVG frames, the BoxType is ignored.
|
// For non-outer SVG frames, the BoxType is ignored.
|
||||||
*aFrame = f;
|
*aFrame = f;
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
#ifndef LayoutConstants_h___
|
#ifndef LayoutConstants_h___
|
||||||
#define LayoutConstants_h___
|
#define LayoutConstants_h___
|
||||||
|
|
||||||
|
#include "mozilla/EnumSet.h"
|
||||||
#include "nsSize.h" // for NS_MAXSIZE
|
#include "nsSize.h" // for NS_MAXSIZE
|
||||||
|
#include "Units.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constant used to indicate an unconstrained size.
|
* Constant used to indicate an unconstrained size.
|
||||||
@ -26,4 +28,71 @@
|
|||||||
|
|
||||||
#define NS_INTRINSIC_ISIZE_UNKNOWN nscoord_MIN
|
#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___
|
#endif // LayoutConstants_h___
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
#include "nsViewportInfo.h"
|
#include "nsViewportInfo.h"
|
||||||
#include "UnitTransforms.h"
|
#include "UnitTransforms.h"
|
||||||
|
|
||||||
#define MVM_LOG(...)
|
static mozilla::LazyLogModule sApzMvmLog("apz.mobileviewport");
|
||||||
// #define MVM_LOG(...) printf_stderr("MVM: " __VA_ARGS__)
|
#define MVM_LOG(...) MOZ_LOG(sApzMvmLog, LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(MobileViewportManager, nsIDOMEventListener, nsIObserver)
|
NS_IMPL_ISUPPORTS(MobileViewportManager, nsIDOMEventListener, nsIObserver)
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ MobileViewportManager::MobileViewportManager(MVMContext* aContext)
|
|||||||
: mContext(aContext), mIsFirstPaint(false), mPainted(false) {
|
: mContext(aContext), mIsFirstPaint(false), mPainted(false) {
|
||||||
MOZ_ASSERT(mContext);
|
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_ADDED, this, false);
|
||||||
mContext->AddEventListener(DOM_META_CHANGED, 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.
|
// for calculating the path length. We may need to update this.
|
||||||
// https://github.com/w3c/fxtf-drafts/issues/369
|
// https://github.com/w3c/fxtf-drafts/issues/369
|
||||||
// FIXME: Bug 1579294: SVG layout may get a |container| with empty mRect
|
// 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();
|
const nsIFrame* container = aFrame->GetContainingBlock();
|
||||||
if (!container) {
|
if (!container) {
|
||||||
// If there is no parent frame, it's impossible to calculate the path
|
// If there is no parent frame, it's impossible to calculate the path
|
||||||
|
@ -114,16 +114,16 @@ class OverflowChangedTracker {
|
|||||||
frame->GetProperty(nsIFrame::DebugInitialOverflowPropertyApplied()),
|
frame->GetProperty(nsIFrame::DebugInitialOverflowPropertyApplied()),
|
||||||
"InitialOverflowProperty must be set first.");
|
"InitialOverflowProperty must be set first.");
|
||||||
|
|
||||||
nsOverflowAreas* overflow =
|
OverflowAreas* overflow =
|
||||||
frame->GetProperty(nsIFrame::InitialOverflowProperty());
|
frame->GetProperty(nsIFrame::InitialOverflowProperty());
|
||||||
if (overflow) {
|
if (overflow) {
|
||||||
// FinishAndStoreOverflow will change the overflow areas passed in,
|
// FinishAndStoreOverflow will change the overflow areas passed in,
|
||||||
// so make a copy.
|
// so make a copy.
|
||||||
nsOverflowAreas overflowCopy = *overflow;
|
OverflowAreas overflowCopy = *overflow;
|
||||||
frame->FinishAndStoreOverflow(overflowCopy, frame->GetSize());
|
frame->FinishAndStoreOverflow(overflowCopy, frame->GetSize());
|
||||||
} else {
|
} else {
|
||||||
nsRect bounds(nsPoint(0, 0), frame->GetSize());
|
nsRect bounds(nsPoint(0, 0), frame->GetSize());
|
||||||
nsOverflowAreas boundsOverflow;
|
OverflowAreas boundsOverflow;
|
||||||
boundsOverflow.SetAllTo(bounds);
|
boundsOverflow.SetAllTo(bounds);
|
||||||
frame->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
|
frame->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/dom/MouseEventBinding.h"
|
#include "mozilla/dom/MouseEventBinding.h"
|
||||||
|
#include "nsFrameList.h" // for DEBUG_FRAME_DUMP
|
||||||
#include "nsHTMLParts.h"
|
#include "nsHTMLParts.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
@ -26,10 +27,11 @@
|
|||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
// If debugging this code you may wish to enable this logging, and also
|
// If debugging this code you may wish to enable this logging, via
|
||||||
// uncomment the DumpFrameTree call near the bottom of the file.
|
// the env var MOZ_LOG="event.retarget:4". For extra logging (getting
|
||||||
#define PET_LOG(...)
|
// frame dumps, use MOZ_LOG="event.retarget:5".
|
||||||
// #define PET_LOG(...) printf_stderr("PET: " __VA_ARGS__);
|
static mozilla::LazyLogModule sEvtTgtLog("event.retarget");
|
||||||
|
#define PET_LOG(...) MOZ_LOG(sEvtTgtLog, LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
@ -246,12 +248,14 @@ static nsIContent* GetClickableAncestor(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nscoord AppUnitsFromMM(nsIFrame* aFrame, uint32_t aMM) {
|
static nscoord AppUnitsFromMM(RelativeTo aFrame, uint32_t aMM) {
|
||||||
nsPresContext* pc = aFrame->PresContext();
|
nsPresContext* pc = aFrame.mFrame->PresContext();
|
||||||
PresShell* presShell = pc->PresShell();
|
|
||||||
float result = float(aMM) * (pc->DeviceContext()->AppUnitsPerPhysicalInch() /
|
float result = float(aMM) * (pc->DeviceContext()->AppUnitsPerPhysicalInch() /
|
||||||
MM_PER_INCH_FLOAT);
|
MM_PER_INCH_FLOAT);
|
||||||
result = result / presShell->GetResolution();
|
if (aFrame.mViewportType == ViewportType::Layout) {
|
||||||
|
PresShell* presShell = pc->PresShell();
|
||||||
|
result = result / presShell->GetResolution();
|
||||||
|
}
|
||||||
return NSToCoordRound(result);
|
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
|
* Clip aRect with the bounds of aFrame in the coordinate system of
|
||||||
* aRootFrame. aRootFrame is an ancestor of aFrame.
|
* 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& aRect) {
|
||||||
nsRect bound = nsLayoutUtils::TransformFrameRectToAncestor(
|
nsRect bound = nsLayoutUtils::TransformFrameRectToAncestor(
|
||||||
aFrame, nsRect(nsPoint(0, 0), aFrame->GetSize()), aRootFrame);
|
aFrame, nsRect(nsPoint(0, 0), aFrame->GetSize()), aRootFrame);
|
||||||
@ -267,9 +271,9 @@ static nsRect ClipToFrame(nsIFrame* aRootFrame, nsIFrame* aFrame,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsRect GetTargetRect(nsIFrame* aRootFrame,
|
static nsRect GetTargetRect(RelativeTo aRootFrame,
|
||||||
const nsPoint& aPointRelativeToRootFrame,
|
const nsPoint& aPointRelativeToRootFrame,
|
||||||
nsIFrame* aRestrictToDescendants,
|
const nsIFrame* aRestrictToDescendants,
|
||||||
const EventRadiusPrefs* aPrefs, uint32_t aFlags) {
|
const EventRadiusPrefs* aPrefs, uint32_t aFlags) {
|
||||||
nsMargin m(AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[0]),
|
nsMargin m(AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[0]),
|
||||||
AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[1]),
|
AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[1]),
|
||||||
@ -325,23 +329,26 @@ static void SubtractFromExposedRegion(nsRegion* aExposedRegion,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsIFrame* GetClosest(
|
static nsIFrame* GetClosest(RelativeTo aRoot,
|
||||||
nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
|
const nsPoint& aPointRelativeToRootFrame,
|
||||||
const nsRect& aTargetRect, const EventRadiusPrefs* aPrefs,
|
const nsRect& aTargetRect,
|
||||||
nsIFrame* aRestrictToDescendants, nsIContent* aClickableAncestor,
|
const EventRadiusPrefs* aPrefs,
|
||||||
nsTArray<nsIFrame*>& aCandidates) {
|
const nsIFrame* aRestrictToDescendants,
|
||||||
|
nsIContent* aClickableAncestor,
|
||||||
|
nsTArray<nsIFrame*>& aCandidates) {
|
||||||
nsIFrame* bestTarget = nullptr;
|
nsIFrame* bestTarget = nullptr;
|
||||||
// Lower is better; distance is in appunits
|
// Lower is better; distance is in appunits
|
||||||
float bestDistance = 1e6f;
|
float bestDistance = 1e6f;
|
||||||
nsRegion exposedRegion(aTargetRect);
|
nsRegion exposedRegion(aTargetRect);
|
||||||
for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
|
for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
|
||||||
nsIFrame* f = aCandidates[i];
|
nsIFrame* f = aCandidates[i];
|
||||||
PET_LOG("Checking candidate %p\n", f);
|
|
||||||
|
|
||||||
bool preservesAxisAlignedRectangles = false;
|
bool preservesAxisAlignedRectangles = false;
|
||||||
nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(
|
nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(
|
||||||
f, nsRect(nsPoint(0, 0), f->GetSize()), aRoot,
|
f, nsRect(nsPoint(0, 0), f->GetSize()), aRoot,
|
||||||
&preservesAxisAlignedRectangles);
|
&preservesAxisAlignedRectangles);
|
||||||
|
PET_LOG("Checking candidate %p with border box %s\n", f,
|
||||||
|
mozilla::layers::Stringify(borderBox).c_str());
|
||||||
nsRegion region;
|
nsRegion region;
|
||||||
region.And(exposedRegion, borderBox);
|
region.And(exposedRegion, borderBox);
|
||||||
if (region.IsEmpty()) {
|
if (region.IsEmpty()) {
|
||||||
@ -370,13 +377,13 @@ static nsIFrame* GetClosest(
|
|||||||
}
|
}
|
||||||
// If our current closest frame is a descendant of 'f', skip 'f' (prefer
|
// If our current closest frame is a descendant of 'f', skip 'f' (prefer
|
||||||
// the nested frame).
|
// the nested frame).
|
||||||
if (bestTarget &&
|
if (bestTarget && nsLayoutUtils::IsProperAncestorFrameCrossDoc(
|
||||||
nsLayoutUtils::IsProperAncestorFrameCrossDoc(f, bestTarget, aRoot)) {
|
f, bestTarget, aRoot.mFrame)) {
|
||||||
PET_LOG(" candidate %p was ancestor for bestTarget %p\n", f, bestTarget);
|
PET_LOG(" candidate %p was ancestor for bestTarget %p\n", f, bestTarget);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!aClickableAncestor && !nsLayoutUtils::IsAncestorFrameCrossDoc(
|
if (!aClickableAncestor && !nsLayoutUtils::IsAncestorFrameCrossDoc(
|
||||||
aRestrictToDescendants, f, aRoot)) {
|
aRestrictToDescendants, f, aRoot.mFrame)) {
|
||||||
PET_LOG(" candidate %p was not descendant of restrictroot %p\n", f,
|
PET_LOG(" candidate %p was not descendant of restrictroot %p\n", f,
|
||||||
aRestrictToDescendants);
|
aRestrictToDescendants);
|
||||||
continue;
|
continue;
|
||||||
@ -401,7 +408,7 @@ static nsIFrame* GetClosest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* FindFrameTargetedByInputEvent(
|
nsIFrame* FindFrameTargetedByInputEvent(
|
||||||
WidgetGUIEvent* aEvent, nsIFrame* aRootFrame,
|
WidgetGUIEvent* aEvent, RelativeTo aRootFrame,
|
||||||
const nsPoint& aPointRelativeToRootFrame, uint32_t aFlags) {
|
const nsPoint& aPointRelativeToRootFrame, uint32_t aFlags) {
|
||||||
using FrameForPointOption = nsLayoutUtils::FrameForPointOption;
|
using FrameForPointOption = nsLayoutUtils::FrameForPointOption;
|
||||||
EnumSet<FrameForPointOption> options;
|
EnumSet<FrameForPointOption> options;
|
||||||
@ -411,17 +418,14 @@ nsIFrame* FindFrameTargetedByInputEvent(
|
|||||||
nsIFrame* target = nsLayoutUtils::GetFrameForPoint(
|
nsIFrame* target = nsLayoutUtils::GetFrameForPoint(
|
||||||
aRootFrame, aPointRelativeToRootFrame, options);
|
aRootFrame, aPointRelativeToRootFrame, options);
|
||||||
PET_LOG(
|
PET_LOG(
|
||||||
"Found initial target %p for event class %s point %s relative to root "
|
"Found initial target %p for event class %s message %s point %s "
|
||||||
"frame %p\n",
|
"relative to root frame %s\n",
|
||||||
target,
|
target, ToChar(aEvent->mClass), ToChar(aEvent->mMessage),
|
||||||
(aEvent->mClass == eMouseEventClass
|
|
||||||
? "mouse"
|
|
||||||
: (aEvent->mClass == eTouchEventClass ? "touch" : "other")),
|
|
||||||
mozilla::layers::Stringify(aPointRelativeToRootFrame).c_str(),
|
mozilla::layers::Stringify(aPointRelativeToRootFrame).c_str(),
|
||||||
aRootFrame);
|
ToString(aRootFrame).c_str());
|
||||||
|
|
||||||
const EventRadiusPrefs* prefs = GetPrefsFor(aEvent->mClass);
|
const EventRadiusPrefs* prefs = GetPrefsFor(aEvent->mClass);
|
||||||
if (!prefs || !prefs->mEnabled) {
|
if (!prefs || !prefs->mEnabled || EventRetargetSuppression::IsActive()) {
|
||||||
PET_LOG("Retargeting disabled\n");
|
PET_LOG("Retargeting disabled\n");
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
@ -452,8 +456,8 @@ nsIFrame* FindFrameTargetedByInputEvent(
|
|||||||
// a mouse event handler for example, targets that are !GetClickableAncestor
|
// a mouse event handler for example, targets that are !GetClickableAncestor
|
||||||
// can never be targeted --- something nsSubDocumentFrame in an ancestor
|
// can never be targeted --- something nsSubDocumentFrame in an ancestor
|
||||||
// document would be targeted instead.
|
// document would be targeted instead.
|
||||||
nsIFrame* restrictToDescendants =
|
const nsIFrame* restrictToDescendants =
|
||||||
target ? target->PresShell()->GetRootFrame() : aRootFrame;
|
target ? target->PresShell()->GetRootFrame() : aRootFrame.mFrame;
|
||||||
|
|
||||||
nsRect targetRect = GetTargetRect(aRootFrame, aPointRelativeToRootFrame,
|
nsRect targetRect = GetTargetRect(aRootFrame, aPointRelativeToRootFrame,
|
||||||
restrictToDescendants, prefs, aFlags);
|
restrictToDescendants, prefs, aFlags);
|
||||||
@ -466,18 +470,22 @@ nsIFrame* FindFrameTargetedByInputEvent(
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* closestClickable = GetClosest(
|
nsIFrame* closestClickable =
|
||||||
aRootFrame, aPointRelativeToRootFrame, targetRect, prefs,
|
GetClosest(aRootFrame, aPointRelativeToRootFrame, targetRect, prefs,
|
||||||
restrictToDescendants, clickableAncestor, candidates);
|
restrictToDescendants, clickableAncestor, candidates);
|
||||||
if (closestClickable) {
|
if (closestClickable) {
|
||||||
target = closestClickable;
|
target = closestClickable;
|
||||||
}
|
}
|
||||||
PET_LOG("Final target is %p\n", target);
|
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
|
// 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.
|
// 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) {
|
if (!target || !prefs->mRepositionEventCoords) {
|
||||||
// No repositioning required for this event
|
// 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.
|
// clamp it to the bounds, and then make it relative to the root frame again.
|
||||||
nsPoint point = aPointRelativeToRootFrame;
|
nsPoint point = aPointRelativeToRootFrame;
|
||||||
if (nsLayoutUtils::TRANSFORM_SUCCEEDED !=
|
if (nsLayoutUtils::TRANSFORM_SUCCEEDED !=
|
||||||
nsLayoutUtils::TransformPoint(aRootFrame, target, point)) {
|
nsLayoutUtils::TransformPoint(aRootFrame, RelativeTo{target}, point)) {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
point = target->GetRectRelativeToSelf().ClampPoint(point);
|
point = target->GetRectRelativeToSelf().ClampPoint(point);
|
||||||
if (nsLayoutUtils::TRANSFORM_SUCCEEDED !=
|
if (nsLayoutUtils::TRANSFORM_SUCCEEDED !=
|
||||||
nsLayoutUtils::TransformPoint(target, aRootFrame, point)) {
|
nsLayoutUtils::TransformPoint(RelativeTo{target}, aRootFrame, point)) {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
// Now we basically undo the operations in GetEventCoordinatesRelativeTo, to
|
// Now we basically undo the operations in GetEventCoordinatesRelativeTo, to
|
||||||
// get back the (now-clamped) coordinates in the event's widget's space.
|
// get back the (now-clamped) coordinates in the event's widget's space.
|
||||||
nsView* view = aRootFrame->GetView();
|
nsView* view = aRootFrame.mFrame->GetView();
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
LayoutDeviceIntPoint widgetPoint = nsLayoutUtils::TranslateViewToWidget(
|
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 (widgetPoint.x != NS_UNCONSTRAINEDSIZE) {
|
||||||
// If that succeeded, we update the point in the event
|
// If that succeeded, we update the point in the event
|
||||||
aEvent->mRefPoint = widgetPoint;
|
aEvent->mRefPoint = widgetPoint;
|
||||||
@ -511,4 +520,12 @@ nsIFrame* FindFrameTargetedByInputEvent(
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t EventRetargetSuppression::sSuppressionCount = 0;
|
||||||
|
|
||||||
|
EventRetargetSuppression::EventRetargetSuppression() { sSuppressionCount++; }
|
||||||
|
|
||||||
|
EventRetargetSuppression::~EventRetargetSuppression() { sSuppressionCount--; }
|
||||||
|
|
||||||
|
bool EventRetargetSuppression::IsActive() { return sSuppressionCount > 0; }
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
|
#include "RelativeTo.h"
|
||||||
|
|
||||||
class nsIFrame;
|
class nsIFrame;
|
||||||
struct nsPoint;
|
struct nsPoint;
|
||||||
@ -20,9 +21,19 @@ enum { INPUT_IGNORE_ROOT_SCROLL_FRAME = 0x01 };
|
|||||||
* that are suitable targets, to account for inaccurate pointing devices.
|
* that are suitable targets, to account for inaccurate pointing devices.
|
||||||
*/
|
*/
|
||||||
nsIFrame* FindFrameTargetedByInputEvent(
|
nsIFrame* FindFrameTargetedByInputEvent(
|
||||||
WidgetGUIEvent* aEvent, nsIFrame* aRootFrame,
|
WidgetGUIEvent* aEvent, RelativeTo aRootFrame,
|
||||||
const nsPoint& aPointRelativeToRootFrame, uint32_t aFlags = 0);
|
const nsPoint& aPointRelativeToRootFrame, uint32_t aFlags = 0);
|
||||||
|
|
||||||
|
class MOZ_RAII EventRetargetSuppression {
|
||||||
|
public:
|
||||||
|
EventRetargetSuppression();
|
||||||
|
~EventRetargetSuppression();
|
||||||
|
static bool IsActive();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static uint32_t sSuppressionCount;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif /* mozilla_PositionedEventTargeting_h */
|
#endif /* mozilla_PositionedEventTargeting_h */
|
||||||
|
@ -6,11 +6,13 @@
|
|||||||
|
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
|
|
||||||
|
#include "Units.h"
|
||||||
#include "mozilla/dom/FontFaceSet.h"
|
#include "mozilla/dom/FontFaceSet.h"
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/AutoRestore.h"
|
#include "mozilla/AutoRestore.h"
|
||||||
#include "mozilla/ContentIterator.h"
|
#include "mozilla/ContentIterator.h"
|
||||||
|
#include "mozilla/DisplayPortUtils.h"
|
||||||
#include "mozilla/EventDispatcher.h"
|
#include "mozilla/EventDispatcher.h"
|
||||||
#include "mozilla/EventStateManager.h"
|
#include "mozilla/EventStateManager.h"
|
||||||
#include "mozilla/EventStates.h"
|
#include "mozilla/EventStates.h"
|
||||||
@ -33,6 +35,7 @@
|
|||||||
#include "mozilla/TouchEvents.h"
|
#include "mozilla/TouchEvents.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
#include "mozilla/ViewportUtils.h"
|
||||||
#include "MobileViewportManager.h"
|
#include "MobileViewportManager.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -116,9 +119,9 @@
|
|||||||
#include "nsStyleSheetService.h"
|
#include "nsStyleSheetService.h"
|
||||||
#include "gfxUtils.h"
|
#include "gfxUtils.h"
|
||||||
#include "mozilla/SMILAnimationController.h"
|
#include "mozilla/SMILAnimationController.h"
|
||||||
#include "SVGContentUtils.h"
|
#include "mozilla/dom/SVGAnimationElement.h"
|
||||||
#include "SVGObserverUtils.h"
|
#include "mozilla/SVGObserverUtils.h"
|
||||||
#include "SVGFragmentIdentifier.h"
|
#include "mozilla/SVGFragmentIdentifier.h"
|
||||||
#include "nsFrameSelection.h"
|
#include "nsFrameSelection.h"
|
||||||
|
|
||||||
#include "mozilla/dom/Performance.h"
|
#include "mozilla/dom/Performance.h"
|
||||||
@ -230,6 +233,11 @@ struct RangePaintInfo {
|
|||||||
// offset of builder's reference frame to the root frame
|
// offset of builder's reference frame to the root frame
|
||||||
nsPoint mRootOffset;
|
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)
|
RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
|
||||||
: mRange(aRange),
|
: mRange(aRange),
|
||||||
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false) {
|
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false) {
|
||||||
@ -2304,10 +2312,10 @@ PresShell::ScrollPage(bool aForward) {
|
|||||||
nsIScrollableFrame* scrollFrame =
|
nsIScrollableFrame* scrollFrame =
|
||||||
GetScrollableFrameToScroll(ScrollableDirection::Vertical);
|
GetScrollableFrameToScroll(ScrollableDirection::Vertical);
|
||||||
if (scrollFrame) {
|
if (scrollFrame) {
|
||||||
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::PAGES,
|
scrollFrame->ScrollBy(
|
||||||
ScrollMode::Smooth, nullptr, nullptr,
|
nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::PAGES, ScrollMode::Smooth,
|
||||||
nsIScrollableFrame::NOT_MOMENTUM,
|
nullptr, mozilla::ScrollOrigin::NotSpecified,
|
||||||
nsIScrollableFrame::ENABLE_SNAP);
|
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -2320,10 +2328,10 @@ PresShell::ScrollLine(bool aForward) {
|
|||||||
int32_t lineCount =
|
int32_t lineCount =
|
||||||
Preferences::GetInt("toolkit.scrollbox.verticalScrollDistance",
|
Preferences::GetInt("toolkit.scrollbox.verticalScrollDistance",
|
||||||
NS_DEFAULT_VERTICAL_SCROLL_DISTANCE);
|
NS_DEFAULT_VERTICAL_SCROLL_DISTANCE);
|
||||||
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? lineCount : -lineCount),
|
scrollFrame->ScrollBy(
|
||||||
ScrollUnit::LINES, ScrollMode::Smooth, nullptr,
|
nsIntPoint(0, aForward ? lineCount : -lineCount), ScrollUnit::LINES,
|
||||||
nullptr, nsIScrollableFrame::NOT_MOMENTUM,
|
ScrollMode::Smooth, nullptr, mozilla::ScrollOrigin::NotSpecified,
|
||||||
nsIScrollableFrame::ENABLE_SNAP);
|
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -2336,10 +2344,10 @@ PresShell::ScrollCharacter(bool aRight) {
|
|||||||
int32_t h =
|
int32_t h =
|
||||||
Preferences::GetInt("toolkit.scrollbox.horizontalScrollDistance",
|
Preferences::GetInt("toolkit.scrollbox.horizontalScrollDistance",
|
||||||
NS_DEFAULT_HORIZONTAL_SCROLL_DISTANCE);
|
NS_DEFAULT_HORIZONTAL_SCROLL_DISTANCE);
|
||||||
scrollFrame->ScrollBy(nsIntPoint(aRight ? h : -h, 0), ScrollUnit::LINES,
|
scrollFrame->ScrollBy(
|
||||||
ScrollMode::Smooth, nullptr, nullptr,
|
nsIntPoint(aRight ? h : -h, 0), ScrollUnit::LINES, ScrollMode::Smooth,
|
||||||
nsIScrollableFrame::NOT_MOMENTUM,
|
nullptr, mozilla::ScrollOrigin::NotSpecified,
|
||||||
nsIScrollableFrame::ENABLE_SNAP);
|
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -2349,10 +2357,10 @@ PresShell::CompleteScroll(bool aForward) {
|
|||||||
nsIScrollableFrame* scrollFrame =
|
nsIScrollableFrame* scrollFrame =
|
||||||
GetScrollableFrameToScroll(ScrollableDirection::Vertical);
|
GetScrollableFrameToScroll(ScrollableDirection::Vertical);
|
||||||
if (scrollFrame) {
|
if (scrollFrame) {
|
||||||
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::WHOLE,
|
scrollFrame->ScrollBy(
|
||||||
ScrollMode::Smooth, nullptr, nullptr,
|
nsIntPoint(0, aForward ? 1 : -1), ScrollUnit::WHOLE, ScrollMode::Smooth,
|
||||||
nsIScrollableFrame::NOT_MOMENTUM,
|
nullptr, mozilla::ScrollOrigin::NotSpecified,
|
||||||
nsIScrollableFrame::ENABLE_SNAP);
|
nsIScrollableFrame::NOT_MOMENTUM, nsIScrollableFrame::ENABLE_SNAP);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -2508,6 +2516,10 @@ void PresShell::EndLoad(Document* aDocument) {
|
|||||||
mDocumentLoading = false;
|
mDocumentLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PresShell::IsLayoutFlushObserver() {
|
||||||
|
return GetPresContext()->RefreshDriver()->IsLayoutFlushObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
void PresShell::LoadComplete() {
|
void PresShell::LoadComplete() {
|
||||||
gfxTextPerfMetrics* tp = nullptr;
|
gfxTextPerfMetrics* tp = nullptr;
|
||||||
if (mPresContext) {
|
if (mPresContext) {
|
||||||
@ -2644,7 +2656,7 @@ void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
|
|||||||
|
|
||||||
// Grab |wasDirty| now so we can go ahead and update the bits on
|
// Grab |wasDirty| now so we can go ahead and update the bits on
|
||||||
// subtreeRoot.
|
// subtreeRoot.
|
||||||
bool wasDirty = NS_SUBTREE_DIRTY(subtreeRoot);
|
bool wasDirty = subtreeRoot->IsSubtreeDirty();
|
||||||
subtreeRoot->AddStateBits(aBitToAdd);
|
subtreeRoot->AddStateBits(aBitToAdd);
|
||||||
|
|
||||||
// Determine whether we need to keep looking for the next ancestor
|
// Determine whether we need to keep looking for the next ancestor
|
||||||
@ -2685,8 +2697,7 @@ void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
|
|||||||
for (nsIFrame* a = subtreeRoot;
|
for (nsIFrame* a = subtreeRoot;
|
||||||
a && !CanStopClearingAncestorIntrinsics(a); a = a->GetParent()) {
|
a && !CanStopClearingAncestorIntrinsics(a); a = a->GetParent()) {
|
||||||
a->MarkIntrinsicISizesDirty();
|
a->MarkIntrinsicISizesDirty();
|
||||||
if (a->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
|
if (a->IsAbsolutelyPositioned()) {
|
||||||
a->IsAbsolutelyPositioned()) {
|
|
||||||
// If we get here, 'a' is abspos, so its subtree's intrinsic sizing
|
// 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
|
// has no effect on its ancestors' intrinsic sizing. So, don't loop
|
||||||
// upwards any further.
|
// upwards any further.
|
||||||
@ -2761,7 +2772,7 @@ void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
|
|||||||
|
|
||||||
nsIFrame* child = f;
|
nsIFrame* child = f;
|
||||||
f = f->GetParent();
|
f = f->GetParent();
|
||||||
wasDirty = NS_SUBTREE_DIRTY(f);
|
wasDirty = f->IsSubtreeDirty();
|
||||||
f->ChildIsDirty(child);
|
f->ChildIsDirty(child);
|
||||||
NS_ASSERTION(f->HasAnyStateBits(NS_FRAME_HAS_DIRTY_CHILDREN),
|
NS_ASSERTION(f->HasAnyStateBits(NS_FRAME_HAS_DIRTY_CHILDREN),
|
||||||
"ChildIsDirty didn't do its job");
|
"ChildIsDirty didn't do its job");
|
||||||
@ -2810,18 +2821,6 @@ already_AddRefed<nsIContent> PresShell::GetSelectedContentForScrolling() const {
|
|||||||
return selectedContent.forget();
|
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(
|
nsIScrollableFrame* PresShell::GetScrollableFrameToScrollForContent(
|
||||||
nsIContent* aContent, ScrollableDirection aDirection) {
|
nsIContent* aContent, ScrollableDirection aDirection) {
|
||||||
nsIScrollableFrame* scrollFrame = nullptr;
|
nsIScrollableFrame* scrollFrame = nullptr;
|
||||||
@ -2832,7 +2831,8 @@ nsIScrollableFrame* PresShell::GetScrollableFrameToScrollForContent(
|
|||||||
if (scrollFrame) {
|
if (scrollFrame) {
|
||||||
startFrame = scrollFrame->GetScrolledFrame();
|
startFrame = scrollFrame->GetScrolledFrame();
|
||||||
}
|
}
|
||||||
scrollFrame = GetNearestScrollableFrame(startFrame, aDirection);
|
scrollFrame = nsLayoutUtils::GetNearestScrollableFrameForDirection(
|
||||||
|
startFrame, aDirection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!scrollFrame) {
|
if (!scrollFrame) {
|
||||||
@ -2840,8 +2840,8 @@ nsIScrollableFrame* PresShell::GetScrollableFrameToScrollForContent(
|
|||||||
if (!scrollFrame || !scrollFrame->GetScrolledFrame()) {
|
if (!scrollFrame || !scrollFrame->GetScrolledFrame()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
scrollFrame =
|
scrollFrame = nsLayoutUtils::GetNearestScrollableFrameForDirection(
|
||||||
GetNearestScrollableFrame(scrollFrame->GetScrolledFrame(), aDirection);
|
scrollFrame->GetScrolledFrame(), aDirection);
|
||||||
}
|
}
|
||||||
return scrollFrame;
|
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
|
// Search for anchor in the HTML namespace with a matching name
|
||||||
if (!content && !mDocument->IsHTMLDocument()) {
|
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
|
// Get the list of anchor elements
|
||||||
nsCOMPtr<nsINodeList> list =
|
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.
|
// Loop through the anchors looking for the first one with the given name.
|
||||||
for (uint32_t i = 0; true; i++) {
|
for (uint32_t i = 0; true; i++) {
|
||||||
nsIContent* node = list->Item(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 the target is an animation element, activate the animation
|
||||||
if (content->IsNodeOfType(nsINode::eANIMATION)) {
|
nsCOMPtr<SVGAnimationElement> animationElement = do_QueryInterface(content);
|
||||||
SVGContentUtils::ActivateByHyperlink(content.get());
|
if (animationElement) {
|
||||||
|
animationElement->ActivateByHyperlink();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
NS_NAMED_LITERAL_STRING(top, "top");
|
constexpr auto top = u"top"_ns;
|
||||||
if (nsContentUtils::EqualsIgnoreASCIICase(aAnchorName, top)) {
|
if (nsContentUtils::EqualsIgnoreASCIICase(aAnchorName, top)) {
|
||||||
// Scroll to the top/left if aAnchorName is "top" and there is no element
|
// Scroll to the top/left if aAnchorName is "top" and there is no element
|
||||||
// with such a name or id.
|
// with such a name or id.
|
||||||
@ -3267,19 +3268,12 @@ static void AccumulateFrameBounds(nsIFrame* aContainerFrame, nsIFrame* aFrame,
|
|||||||
if (aLines) {
|
if (aLines) {
|
||||||
int32_t index = aLines->FindLineContaining(prevFrame, aCurLine);
|
int32_t index = aLines->FindLineContaining(prevFrame, aCurLine);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
aCurLine = index;
|
auto line = aLines->GetLine(index).unwrap();
|
||||||
nsIFrame* trash1;
|
frameBounds += frame->GetOffsetTo(f);
|
||||||
int32_t trash2;
|
frame = f;
|
||||||
nsRect lineBounds;
|
if (line.mLineBounds.y < frameBounds.y) {
|
||||||
|
frameBounds.height = frameBounds.YMost() - line.mLineBounds.y;
|
||||||
if (NS_SUCCEEDED(
|
frameBounds.y = line.mLineBounds.y;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3624,7 +3618,8 @@ bool PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame, const nsRect& aRect,
|
|||||||
}
|
}
|
||||||
nsIFrame* parent;
|
nsIFrame* parent;
|
||||||
if (container->IsTransformed()) {
|
if (container->IsTransformed()) {
|
||||||
container->GetTransformMatrix(nullptr, &parent);
|
container->GetTransformMatrix(ViewportType::Layout, RelativeTo{nullptr},
|
||||||
|
&parent);
|
||||||
rect =
|
rect =
|
||||||
nsLayoutUtils::TransformFrameRectToAncestor(container, rect, parent);
|
nsLayoutUtils::TransformFrameRectToAncestor(container, rect, parent);
|
||||||
} else {
|
} else {
|
||||||
@ -4716,8 +4711,8 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
|
|||||||
// XXX deal with frame being null due to display:contents
|
// XXX deal with frame being null due to display:contents
|
||||||
for (; frame;
|
for (; frame;
|
||||||
frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
|
frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
|
||||||
info->mBuilder.SetVisibleRect(frame->GetVisualOverflowRect());
|
info->mBuilder.SetVisibleRect(frame->InkOverflowRect());
|
||||||
info->mBuilder.SetDirtyRect(frame->GetVisualOverflowRect());
|
info->mBuilder.SetDirtyRect(frame->InkOverflowRect());
|
||||||
frame->BuildDisplayListForStackingContext(&info->mBuilder, &info->mList);
|
frame->BuildDisplayListForStackingContext(&info->mBuilder, &info->mList);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -4733,6 +4728,32 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
|
|||||||
BuildDisplayListForNode(endContainer);
|
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
|
#ifdef DEBUG
|
||||||
if (gDumpRangePaintList) {
|
if (gDumpRangePaintList) {
|
||||||
fprintf(stderr, "CreateRangePaintInfo --- before ClipListToRange:\n");
|
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;
|
if (!pc || aArea.width == 0 || aArea.height == 0) return nullptr;
|
||||||
|
|
||||||
// use the rectangle to create the surface
|
// 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
|
// if the image should not be resized, scale must be 1
|
||||||
float scale = 1.0;
|
float scale = 1.0;
|
||||||
nsIntRect rootScreenRect =
|
|
||||||
GetRootFrame()->GetScreenRectInAppUnits().ToNearestPixels(
|
|
||||||
pc->AppUnitsPerDevPixel());
|
|
||||||
|
|
||||||
nsRect maxSize;
|
nsRect maxSize;
|
||||||
pc->DeviceContext()->GetClientRect(maxSize);
|
pc->DeviceContext()->GetClientRect(maxSize);
|
||||||
@ -4788,8 +4807,8 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
|
|||||||
// check if image-resizing-algorithm should be used
|
// check if image-resizing-algorithm should be used
|
||||||
if (aFlags & RenderImageFlags::IsImage) {
|
if (aFlags & RenderImageFlags::IsImage) {
|
||||||
// get max screensize
|
// get max screensize
|
||||||
nscoord maxWidth = pc->AppUnitsToDevPixels(maxSize.width);
|
int32_t maxWidth = pc->AppUnitsToDevPixels(maxSize.width);
|
||||||
nscoord maxHeight = pc->AppUnitsToDevPixels(maxSize.height);
|
int32_t maxHeight = pc->AppUnitsToDevPixels(maxSize.height);
|
||||||
// resize image relative to the screensize
|
// resize image relative to the screensize
|
||||||
// get best height/width relative to screensize
|
// get best height/width relative to screensize
|
||||||
float bestHeight = float(maxHeight) * RELATIVE_SCALEFACTOR;
|
float bestHeight = float(maxHeight) * RELATIVE_SCALEFACTOR;
|
||||||
@ -4808,8 +4827,8 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
|
|||||||
scale = std::min(scale, adjustedScale);
|
scale = std::min(scale, adjustedScale);
|
||||||
} else {
|
} else {
|
||||||
// get half of max screensize
|
// get half of max screensize
|
||||||
nscoord maxWidth = pc->AppUnitsToDevPixels(maxSize.width >> 1);
|
int32_t maxWidth = pc->AppUnitsToDevPixels(maxSize.width >> 1);
|
||||||
nscoord maxHeight = pc->AppUnitsToDevPixels(maxSize.height >> 1);
|
int32_t maxHeight = pc->AppUnitsToDevPixels(maxSize.height >> 1);
|
||||||
if (pixelArea.width > maxWidth || pixelArea.height > maxHeight) {
|
if (pixelArea.width > maxWidth || pixelArea.height > maxHeight) {
|
||||||
// divide the maximum size by the image size in both directions.
|
// divide the maximum size by the image size in both directions.
|
||||||
// Whichever direction produces the smallest result determines how much
|
// 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.width = NSToIntFloor(float(pixelArea.width) * scale);
|
||||||
pixelArea.height = NSToIntFloor(float(pixelArea.height) * scale);
|
pixelArea.height = NSToIntFloor(float(pixelArea.height) * scale);
|
||||||
if (!pixelArea.width || !pixelArea.height) return nullptr;
|
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);
|
|
||||||
} else {
|
} else {
|
||||||
// move aScreenRect to the position of the surface in screen coordinates
|
// move aScreenRect to the position of the surface in screen coordinates
|
||||||
aScreenRect->MoveTo(rootScreenRect.x + pixelArea.x,
|
LayoutDevicePoint visualPoint = ViewportUtils::ToScreenRelativeVisual(
|
||||||
rootScreenRect.y + pixelArea.y);
|
LayoutDevicePoint(pixelArea.TopLeft()), pc);
|
||||||
|
aScreenRect->MoveTo(RoundedToInt(visualPoint));
|
||||||
}
|
}
|
||||||
aScreenRect->width = pixelArea.width;
|
aScreenRect->width = pixelArea.width;
|
||||||
aScreenRect->height = pixelArea.height;
|
aScreenRect->height = pixelArea.height;
|
||||||
@ -4870,7 +4935,9 @@ already_AddRefed<SourceSurface> PresShell::PaintRangePaintInfo(
|
|||||||
|
|
||||||
gfxMatrix initialTM = ctx->CurrentMatrixDouble();
|
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
|
// translate so that points are relative to the surface area
|
||||||
gfxPoint surfaceOffset = nsLayoutUtils::PointToGfxPoint(
|
gfxPoint surfaceOffset = nsLayoutUtils::PointToGfxPoint(
|
||||||
@ -5239,7 +5306,7 @@ nsresult PresShell::SetResolutionAndScaleTo(float aResolution,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
float PresShell::GetCumulativeResolution() {
|
float PresShell::GetCumulativeResolution() const {
|
||||||
float resolution = GetResolution();
|
float resolution = GetResolution();
|
||||||
nsPresContext* parentCtx = GetPresContext()->GetParentPresContext();
|
nsPresContext* parentCtx = GetPresContext()->GetParentPresContext();
|
||||||
if (parentCtx) {
|
if (parentCtx) {
|
||||||
@ -5248,24 +5315,6 @@ float PresShell::GetCumulativeResolution() {
|
|||||||
return resolution;
|
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,
|
void PresShell::SetRestoreResolution(float aResolution,
|
||||||
LayoutDeviceIntSize aDisplaySize) {
|
LayoutDeviceIntSize aDisplaySize) {
|
||||||
if (mMobileViewportManager) {
|
if (mMobileViewportManager) {
|
||||||
@ -5638,7 +5687,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
|
|||||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(aFrame);
|
nsIScrollableFrame* scrollFrame = do_QueryFrame(aFrame);
|
||||||
if (scrollFrame) {
|
if (scrollFrame) {
|
||||||
bool ignoreDisplayPort = false;
|
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
|
// 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
|
// and root content documents. Otherwise the base rect we compute might
|
||||||
// be way too big without the limiting that
|
// be way too big without the limiting that
|
||||||
@ -5650,7 +5699,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
|
|||||||
nsRect baseRect =
|
nsRect baseRect =
|
||||||
nsRect(nsPoint(0, 0),
|
nsRect(nsPoint(0, 0),
|
||||||
nsLayoutUtils::CalculateCompositionSizeForFrame(aFrame));
|
nsLayoutUtils::CalculateCompositionSizeForFrame(aFrame));
|
||||||
nsLayoutUtils::SetDisplayPortBase(aFrame->GetContent(), baseRect);
|
DisplayPortUtils::SetDisplayPortBase(aFrame->GetContent(), baseRect);
|
||||||
} else {
|
} else {
|
||||||
ignoreDisplayPort = true;
|
ignoreDisplayPort = true;
|
||||||
}
|
}
|
||||||
@ -5659,8 +5708,8 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
|
|||||||
nsRect displayPort;
|
nsRect displayPort;
|
||||||
bool usingDisplayport =
|
bool usingDisplayport =
|
||||||
!ignoreDisplayPort &&
|
!ignoreDisplayPort &&
|
||||||
nsLayoutUtils::GetDisplayPortForVisibilityTesting(
|
DisplayPortUtils::GetDisplayPortForVisibilityTesting(
|
||||||
aFrame->GetContent(), &displayPort, RelativeTo::ScrollFrame);
|
aFrame->GetContent(), &displayPort);
|
||||||
|
|
||||||
scrollFrame->NotifyApproximateFrameVisibilityUpdate(!usingDisplayport);
|
scrollFrame->NotifyApproximateFrameVisibilityUpdate(!usingDisplayport);
|
||||||
|
|
||||||
@ -5684,7 +5733,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
|
|||||||
|
|
||||||
for (nsIFrame* child : list) {
|
for (nsIFrame* child : list) {
|
||||||
nsRect r = rect - child->GetPosition();
|
nsRect r = rect - child->GetPosition();
|
||||||
if (!r.IntersectRect(r, child->GetVisualOverflowRect())) {
|
if (!r.IntersectRect(r, child->InkOverflowRect())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (child->IsTransformed()) {
|
if (child->IsTransformed()) {
|
||||||
@ -5692,7 +5741,7 @@ void PresShell::MarkFramesInSubtreeApproximatelyVisible(
|
|||||||
// rect
|
// rect
|
||||||
if (!preserves3DChildren ||
|
if (!preserves3DChildren ||
|
||||||
!child->Combines3DTransformWithAncestors()) {
|
!child->Combines3DTransformWithAncestors()) {
|
||||||
const nsRect overflow = child->GetVisualOverflowRectRelativeToSelf();
|
const nsRect overflow = child->InkOverflowRectRelativeToSelf();
|
||||||
nsRect out;
|
nsRect out;
|
||||||
if (nsDisplayTransform::UntransformRect(r, overflow, child, &out)) {
|
if (nsDisplayTransform::UntransformRect(r, overflow, child, &out)) {
|
||||||
r = out;
|
r = out;
|
||||||
@ -5817,7 +5866,7 @@ bool PresShell::AssumeAllFramesVisible() {
|
|||||||
if (!mHaveShutDown && !mIsDestroying &&
|
if (!mHaveShutDown && !mIsDestroying &&
|
||||||
!mPresContext->IsRootContentDocument()) {
|
!mPresContext->IsRootContentDocument()) {
|
||||||
nsPresContext* presContext =
|
nsPresContext* presContext =
|
||||||
mPresContext->GetToplevelContentDocumentPresContext();
|
mPresContext->GetInProcessRootContentDocumentPresContext();
|
||||||
if (presContext && presContext->PresShell()->AssumeAllFramesVisible()) {
|
if (presContext && presContext->PresShell()->AssumeAllFramesVisible()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -5851,11 +5900,11 @@ void PresShell::ScheduleApproximateFrameVisibilityUpdateNow() {
|
|||||||
|
|
||||||
if (!mPresContext->IsRootContentDocument()) {
|
if (!mPresContext->IsRootContentDocument()) {
|
||||||
nsPresContext* presContext =
|
nsPresContext* presContext =
|
||||||
mPresContext->GetToplevelContentDocumentPresContext();
|
mPresContext->GetInProcessRootContentDocumentPresContext();
|
||||||
if (!presContext) return;
|
if (!presContext) return;
|
||||||
MOZ_ASSERT(presContext->IsRootContentDocument(),
|
MOZ_ASSERT(presContext->IsRootContentDocument(),
|
||||||
"Didn't get a root prescontext from "
|
"Didn't get a root prescontext from "
|
||||||
"GetToplevelContentDocumentPresContext?");
|
"GetInProcessRootContentDocumentPresContext?");
|
||||||
presContext->PresShell()->ScheduleApproximateFrameVisibilityUpdateNow();
|
presContext->PresShell()->ScheduleApproximateFrameVisibilityUpdateNow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -5950,7 +5999,7 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
|
|||||||
if (contentRoot) {
|
if (contentRoot) {
|
||||||
uri = contentRoot->GetDocumentURI();
|
uri = contentRoot->GetDocumentURI();
|
||||||
}
|
}
|
||||||
url = uri ? uri->GetSpecOrDefault() : NS_LITERAL_CSTRING("N/A");
|
url = uri ? uri->GetSpecOrDefault() : "N/A"_ns;
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("PresShell::Paint", GRAPHICS, url);
|
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("PresShell::Paint", GRAPHICS, url);
|
||||||
#endif
|
#endif
|
||||||
@ -6360,8 +6409,8 @@ void PresShell::RecordMouseLocation(WidgetGUIEvent* aEvent) {
|
|||||||
mPresContext, aEvent->mWidget, aEvent->mRefPoint, rootView);
|
mPresContext, aEvent->mWidget, aEvent->mRefPoint, rootView);
|
||||||
mMouseEventTargetGuid = InputAPZContext::GetTargetLayerGuid();
|
mMouseEventTargetGuid = InputAPZContext::GetTargetLayerGuid();
|
||||||
} else {
|
} else {
|
||||||
mMouseLocation =
|
mMouseLocation = nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
||||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, rootFrame);
|
aEvent, RelativeTo{rootFrame, ViewportType::Visual});
|
||||||
mMouseEventTargetGuid = InputAPZContext::GetTargetLayerGuid();
|
mMouseEventTargetGuid = InputAPZContext::GetTargetLayerGuid();
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_MOUSE_LOCATION
|
#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
|
// static
|
||||||
nsIFrame* PresShell::EventHandler::GetNearestFrameContainingPresShell(
|
nsIFrame* PresShell::EventHandler::GetNearestFrameContainingPresShell(
|
||||||
PresShell* aPresShell) {
|
PresShell* aPresShell) {
|
||||||
@ -6701,7 +6758,7 @@ nsresult PresShell::EventHandler::HandleEventUsingCoordinates(
|
|||||||
eventTargetData.mFrame->GetContent(), capturingContent))) {
|
eventTargetData.mFrame->GetContent(), capturingContent))) {
|
||||||
// A check was already done above to ensure that capturingContent is
|
// A check was already done above to ensure that capturingContent is
|
||||||
// in this presshell.
|
// in this presshell.
|
||||||
NS_ASSERTION(capturingContent->GetComposedDoc() == GetDocument(),
|
NS_ASSERTION(capturingContent->OwnerDoc() == GetDocument(),
|
||||||
"Unexpected document");
|
"Unexpected document");
|
||||||
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
|
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
|
||||||
if (capturingFrame) {
|
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* PresShell::EventHandler::GetFrameToHandleNonTouchEvent(
|
||||||
nsIFrame* aRootFrameToHandleEvent, WidgetGUIEvent* aGUIEvent) {
|
nsIFrame* aRootFrameToHandleEvent, WidgetGUIEvent* aGUIEvent) {
|
||||||
MOZ_ASSERT(aGUIEvent);
|
MOZ_ASSERT(aGUIEvent);
|
||||||
MOZ_ASSERT(aGUIEvent->mClass != eTouchEventClass);
|
MOZ_ASSERT(aGUIEvent->mClass != eTouchEventClass);
|
||||||
|
|
||||||
nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
ViewportType viewportType = ViewportType::Layout;
|
||||||
aGUIEvent, aRootFrameToHandleEvent);
|
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;
|
uint32_t flags = 0;
|
||||||
if (aGUIEvent->mClass == eMouseEventClass) {
|
if (aGUIEvent->mClass == eMouseEventClass) {
|
||||||
@ -6807,8 +6892,8 @@ nsIFrame* PresShell::EventHandler::GetFrameToHandleNonTouchEvent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* targetFrame = FindFrameTargetedByInputEvent(
|
nsIFrame* targetFrame =
|
||||||
aGUIEvent, aRootFrameToHandleEvent, eventPoint, flags);
|
FindFrameTargetedByInputEvent(aGUIEvent, relativeTo, eventPoint, flags);
|
||||||
if (!targetFrame) {
|
if (!targetFrame) {
|
||||||
return aRootFrameToHandleEvent;
|
return aRootFrameToHandleEvent;
|
||||||
}
|
}
|
||||||
@ -6837,8 +6922,8 @@ nsIFrame* PresShell::EventHandler::GetFrameToHandleNonTouchEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally, we need to recompute the target with the latest layout.
|
// Finally, we need to recompute the target with the latest layout.
|
||||||
targetFrame = FindFrameTargetedByInputEvent(
|
targetFrame =
|
||||||
aGUIEvent, aRootFrameToHandleEvent, eventPoint, flags);
|
FindFrameTargetedByInputEvent(aGUIEvent, relativeTo, eventPoint, flags);
|
||||||
|
|
||||||
return targetFrame ? targetFrame : aRootFrameToHandleEvent;
|
return targetFrame ? targetFrame : aRootFrameToHandleEvent;
|
||||||
}
|
}
|
||||||
@ -7294,8 +7379,7 @@ bool PresShell::EventHandler::MaybeDiscardOrDelayMouseEvent(
|
|||||||
|
|
||||||
nsCOMPtr<EventTarget> eventTarget = aGUIEvent->mTarget;
|
nsCOMPtr<EventTarget> eventTarget = aGUIEvent->mTarget;
|
||||||
RefPtr<Event> event = EventDispatcher::CreateEvent(
|
RefPtr<Event> event = EventDispatcher::CreateEvent(
|
||||||
eventTarget, aFrameToHandleEvent->PresContext(), aGUIEvent,
|
eventTarget, aFrameToHandleEvent->PresContext(), aGUIEvent, u""_ns);
|
||||||
EmptyString());
|
|
||||||
|
|
||||||
suppressedListener->HandleEvent(*event);
|
suppressedListener->HandleEvent(*event);
|
||||||
return true;
|
return true;
|
||||||
@ -7450,7 +7534,7 @@ PresShell::EventHandler::ComputeRootFrameToHandleEventWithCapturingContent(
|
|||||||
|
|
||||||
// A check was already done above to ensure that aCapturingContent is
|
// A check was already done above to ensure that aCapturingContent is
|
||||||
// in this presshell.
|
// in this presshell.
|
||||||
NS_ASSERTION(aCapturingContent->GetComposedDoc() == GetDocument(),
|
NS_ASSERTION(aCapturingContent->OwnerDoc() == GetDocument(),
|
||||||
"Unexpected document");
|
"Unexpected document");
|
||||||
nsIFrame* captureFrame = aCapturingContent->GetPrimaryFrame();
|
nsIFrame* captureFrame = aCapturingContent->GetPrimaryFrame();
|
||||||
if (!captureFrame) {
|
if (!captureFrame) {
|
||||||
@ -8568,6 +8652,12 @@ bool PresShell::EventHandler::AdjustContextMenuKeyEvent(
|
|||||||
if (PrepareToUseCaretPosition(MOZ_KnownLive(aMouseEvent->mWidget),
|
if (PrepareToUseCaretPosition(MOZ_KnownLive(aMouseEvent->mWidget),
|
||||||
caretPoint)) {
|
caretPoint)) {
|
||||||
// caret position is good
|
// caret position is good
|
||||||
|
int32_t devPixelRatio = GetPresContext()->AppUnitsPerDevPixel();
|
||||||
|
caretPoint = LayoutDeviceIntPoint::FromAppUnitsToNearest(
|
||||||
|
ViewportUtils::LayoutToVisual(
|
||||||
|
LayoutDeviceIntPoint::ToAppUnits(caretPoint, devPixelRatio),
|
||||||
|
GetPresContext()->PresShell()),
|
||||||
|
devPixelRatio);
|
||||||
aMouseEvent->mRefPoint = caretPoint;
|
aMouseEvent->mRefPoint = caretPoint;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -9172,8 +9262,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
nsIURI* uri = mDocument->GetDocumentURI();
|
nsIURI* uri = mDocument->GetDocumentURI();
|
||||||
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(
|
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(
|
||||||
"Reflow", LAYOUT_Reflow,
|
"Reflow", LAYOUT_Reflow, uri ? uri->GetSpecOrDefault() : "N/A"_ns);
|
||||||
uri ? uri->GetSpecOrDefault() : NS_LITERAL_CSTRING("N/A"));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gfxTextPerfMetrics* tp = mPresContext->GetTextPerfMetrics();
|
gfxTextPerfMetrics* tp = mPresContext->GetTextPerfMetrics();
|
||||||
@ -9239,7 +9328,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||||||
size = target->GetLogicalSize();
|
size = target->GetLogicalSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsOverflowAreas oldOverflow; // initialized and used only when !isRoot
|
OverflowAreas oldOverflow; // initialized and used only when !isRoot
|
||||||
if (!isRoot) {
|
if (!isRoot) {
|
||||||
oldOverflow = target->GetOverflowAreas();
|
oldOverflow = target->GetOverflowAreas();
|
||||||
}
|
}
|
||||||
@ -9251,7 +9340,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||||||
// constrained height implies page/column breaking.
|
// constrained height implies page/column breaking.
|
||||||
LogicalSize reflowSize(wm, size.ISize(wm), NS_UNCONSTRAINEDSIZE);
|
LogicalSize reflowSize(wm, size.ISize(wm), NS_UNCONSTRAINEDSIZE);
|
||||||
ReflowInput reflowInput(mPresContext, target, rcx, reflowSize,
|
ReflowInput reflowInput(mPresContext, target, rcx, reflowSize,
|
||||||
ReflowInput::CALLER_WILL_INIT);
|
ReflowInput::InitFlag::CallerWillInit);
|
||||||
reflowInput.mOrthogonalLimit = size.BSize(wm);
|
reflowInput.mOrthogonalLimit = size.BSize(wm);
|
||||||
|
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
@ -9275,9 +9364,9 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||||||
// Initialize reflow input with current used border and padding,
|
// Initialize reflow input with current used border and padding,
|
||||||
// in case this was set specially by the parent frame when the reflow root
|
// in case this was set specially by the parent frame when the reflow root
|
||||||
// was reflowed by its parent.
|
// was reflowed by its parent.
|
||||||
nsMargin currentBorder = target->GetUsedBorder();
|
reflowInput.Init(mPresContext, Nothing(),
|
||||||
nsMargin currentPadding = target->GetUsedPadding();
|
Some(target->GetLogicalUsedBorder(wm)),
|
||||||
reflowInput.Init(mPresContext, Nothing(), ¤tBorder, ¤tPadding);
|
Some(target->GetLogicalUsedPadding(wm)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix the computed height
|
// fix the computed height
|
||||||
@ -9286,14 +9375,15 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||||||
if (size.BSize(wm) != NS_UNCONSTRAINEDSIZE) {
|
if (size.BSize(wm) != NS_UNCONSTRAINEDSIZE) {
|
||||||
nscoord computedBSize =
|
nscoord computedBSize =
|
||||||
size.BSize(wm) -
|
size.BSize(wm) -
|
||||||
reflowInput.ComputedLogicalBorderPadding().BStartEnd(wm);
|
reflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(wm);
|
||||||
computedBSize = std::max(computedBSize, 0);
|
computedBSize = std::max(computedBSize, 0);
|
||||||
reflowInput.SetComputedBSize(computedBSize);
|
reflowInput.SetComputedBSize(computedBSize);
|
||||||
}
|
}
|
||||||
NS_ASSERTION(reflowInput.ComputedISize() ==
|
NS_ASSERTION(
|
||||||
size.ISize(wm) -
|
reflowInput.ComputedISize() ==
|
||||||
reflowInput.ComputedLogicalBorderPadding().IStartEnd(wm),
|
size.ISize(wm) -
|
||||||
"reflow input computed incorrect inline size");
|
reflowInput.ComputedLogicalBorderPadding(wm).IStartEnd(wm),
|
||||||
|
"reflow input computed incorrect inline size");
|
||||||
|
|
||||||
mPresContext->ReflowStarted(aInterruptible);
|
mPresContext->ReflowStarted(aInterruptible);
|
||||||
mIsReflowing = true;
|
mIsReflowing = true;
|
||||||
@ -9318,7 +9408,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||||||
target->SetSize(boundsRelativeToTarget.Size());
|
target->SetSize(boundsRelativeToTarget.Size());
|
||||||
|
|
||||||
// Always use boundsRelativeToTarget here, not
|
// 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
|
// could be different, since root frames are allowed to have overflow) the
|
||||||
// root view bounds need to match the viewport bounds; the view manager
|
// root view bounds need to match the viewport bounds; the view manager
|
||||||
// "window dimensions" code depends on it.
|
// "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()) {
|
for (auto iter = mFramesToDirty.Iter(); !iter.Done(); iter.Next()) {
|
||||||
// Mark frames dirty until target frame.
|
// Mark frames dirty until target frame.
|
||||||
nsPtrHashKey<nsIFrame>* p = iter.Get();
|
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 = f->GetParent()) {
|
||||||
f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||||
if (f->IsFlexItem()) {
|
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);
|
mDirtyRoots.Add(target);
|
||||||
SetNeedLayoutFlush();
|
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.
|
// assertion so that if it fails it's easier to see what's going on.
|
||||||
#ifdef NOISY_INTERRUPTIBLE_REFLOW
|
#ifdef NOISY_INTERRUPTIBLE_REFLOW
|
||||||
printf("mFramesToDirty.Count() == %u\n", mFramesToDirty.Count());
|
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.
|
// Send an incremental reflow notification to the target frame.
|
||||||
nsIFrame* target = mDirtyRoots.PopShallowestRoot();
|
nsIFrame* target = mDirtyRoots.PopShallowestRoot();
|
||||||
|
|
||||||
if (!NS_SUBTREE_DIRTY(target)) {
|
if (!target->IsSubtreeDirty()) {
|
||||||
// It's not dirty anymore, which probably means the notification
|
// It's not dirty anymore, which probably means the notification
|
||||||
// was posted in the middle of a reflow (perhaps with a reflow
|
// was posted in the middle of a reflow (perhaps with a reflow
|
||||||
// root in the middle). Don't do anything.
|
// 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) {
|
void PresShell::ListStyleSheets(FILE* out, int32_t aIndent) {
|
||||||
int32_t sheetCount = StyleSet()->SheetCount(StyleOrigin::Author);
|
auto ListStyleSheetsAtOrigin = [this, out, aIndent](StyleOrigin origin) {
|
||||||
for (int32_t i = 0; i < sheetCount; ++i) {
|
int32_t sheetCount = StyleSet()->SheetCount(origin);
|
||||||
StyleSet()->SheetAt(StyleOrigin::Author, i)->List(out, aIndent);
|
for (int32_t i = 0; i < sheetCount; ++i) {
|
||||||
fputs("\n", out);
|
StyleSet()->SheetAt(origin, i)->List(out, aIndent);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ListStyleSheetsAtOrigin(StyleOrigin::UserAgent);
|
||||||
|
ListStyleSheetsAtOrigin(StyleOrigin::User);
|
||||||
|
ListStyleSheetsAtOrigin(StyleOrigin::Author);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -10768,21 +10865,39 @@ void PresShell::ResetVisualViewportSize() {
|
|||||||
|
|
||||||
bool PresShell::SetVisualViewportOffset(const nsPoint& aScrollOffset,
|
bool PresShell::SetVisualViewportOffset(const nsPoint& aScrollOffset,
|
||||||
const nsPoint& aPrevLayoutScrollPos) {
|
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();
|
nsPoint prevOffset = GetVisualViewportOffset();
|
||||||
if (prevOffset == aScrollOffset) {
|
if (prevOffset == newOffset) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mVisualViewportOffset = Some(aScrollOffset);
|
mVisualViewportOffset = Some(newOffset);
|
||||||
|
|
||||||
if (auto* window = nsGlobalWindowInner::Cast(mDocument->GetInnerWindow())) {
|
if (auto* window = nsGlobalWindowInner::Cast(mDocument->GetInnerWindow())) {
|
||||||
window->VisualViewport()->PostScrollEvent(prevOffset, aPrevLayoutScrollPos);
|
window->VisualViewport()->PostScrollEvent(prevOffset, aPrevLayoutScrollPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsVisualViewportSizeSet()) {
|
if (IsVisualViewportSizeSet() && rootScrollFrame) {
|
||||||
|
rootScrollFrame->Anchor()->UserScrolled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gfxPlatform::UseDesktopZoomingScrollbars()) {
|
||||||
if (nsIScrollableFrame* rootScrollFrame =
|
if (nsIScrollableFrame* rootScrollFrame =
|
||||||
GetRootScrollFrameAsScrollable()) {
|
GetRootScrollFrameAsScrollable()) {
|
||||||
rootScrollFrame->Anchor()->UserScrolled();
|
rootScrollFrame->UpdateScrollbarPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11048,14 +11163,15 @@ nsIContent* PresShell::EventHandler::GetOverrideClickTarget(
|
|||||||
WidgetMouseEvent* mouseEvent = aGUIEvent->AsMouseEvent();
|
WidgetMouseEvent* mouseEvent = aGUIEvent->AsMouseEvent();
|
||||||
|
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
RelativeTo relativeTo{aFrame};
|
||||||
nsPoint eventPoint =
|
nsPoint eventPoint =
|
||||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aGUIEvent, aFrame);
|
nsLayoutUtils::GetEventCoordinatesRelativeTo(aGUIEvent, relativeTo);
|
||||||
if (mouseEvent->mIgnoreRootScrollFrame) {
|
if (mouseEvent->mIgnoreRootScrollFrame) {
|
||||||
flags |= INPUT_IGNORE_ROOT_SCROLL_FRAME;
|
flags |= INPUT_IGNORE_ROOT_SCROLL_FRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* target =
|
nsIFrame* target =
|
||||||
FindFrameTargetedByInputEvent(aGUIEvent, aFrame, eventPoint, flags);
|
FindFrameTargetedByInputEvent(aGUIEvent, relativeTo, eventPoint, flags);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
return nullptr;
|
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 "nsPresArena.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
#include "nsRefreshDriver.h"
|
#include "nsRefreshObservers.h"
|
||||||
#include "nsStringFwd.h"
|
#include "nsStringFwd.h"
|
||||||
#include "nsStubDocumentObserver.h"
|
#include "nsStubDocumentObserver.h"
|
||||||
#include "nsTHashtable.h"
|
#include "nsTHashtable.h"
|
||||||
@ -70,6 +70,7 @@ class nsITimer;
|
|||||||
class nsPIDOMWindowOuter;
|
class nsPIDOMWindowOuter;
|
||||||
class nsPresShellEventCB;
|
class nsPresShellEventCB;
|
||||||
class nsRange;
|
class nsRange;
|
||||||
|
class nsRefreshDriver;
|
||||||
class nsRegion;
|
class nsRegion;
|
||||||
class nsView;
|
class nsView;
|
||||||
class nsViewManager;
|
class nsViewManager;
|
||||||
@ -83,6 +84,8 @@ class ZoomConstraintsClient;
|
|||||||
|
|
||||||
struct nsCallbackEventRequest;
|
struct nsCallbackEventRequest;
|
||||||
|
|
||||||
|
enum class ScrollableDirection;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class AccessibleCaretEventHub;
|
class AccessibleCaretEventHub;
|
||||||
class EventStates;
|
class EventStates;
|
||||||
@ -369,9 +372,7 @@ class PresShell final : public nsStubDocumentObserver,
|
|||||||
/**
|
/**
|
||||||
* Return true if the presshell expects layout flush.
|
* Return true if the presshell expects layout flush.
|
||||||
*/
|
*/
|
||||||
bool IsLayoutFlushObserver() {
|
bool IsLayoutFlushObserver();
|
||||||
return GetPresContext()->RefreshDriver()->IsLayoutFlushObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when document load completes.
|
* Called when document load completes.
|
||||||
@ -423,15 +424,6 @@ class PresShell final : public nsStubDocumentObserver,
|
|||||||
nsIScrollableFrame* GetScrollableFrameToScroll(
|
nsIScrollableFrame* GetScrollableFrameToScroll(
|
||||||
ScrollableDirection aDirection);
|
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 the page sequence frame associated with the frame hierarchy.
|
||||||
* Returns nullptr if not a paginated view.
|
* 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
|
* Scrolls the view of the document so that the given area of a frame
|
||||||
* is visible, if possible. Layout is not flushed before scrolling.
|
* 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 aVertical see ScrollContentIntoView and ScrollAxis
|
||||||
* @param aHorizontal see ScrollContentIntoView and ScrollAxis
|
* @param aHorizontal see ScrollContentIntoView and ScrollAxis
|
||||||
* @param aScrollFlags if SCROLL_FIRST_ANCESTOR_ONLY is set, only the
|
* @param aScrollFlags if SCROLL_FIRST_ANCESTOR_ONLY is set, only the
|
||||||
@ -717,12 +710,13 @@ class PresShell final : public nsStubDocumentObserver,
|
|||||||
bool IsPaintingFrameCounts();
|
bool IsPaintingFrameCounts();
|
||||||
#endif // #ifdef MOZ_REFLOW_PERF
|
#endif // #ifdef MOZ_REFLOW_PERF
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Debugging hooks
|
// Debugging hooks
|
||||||
|
#ifdef DEBUG
|
||||||
void ListComputedStyles(FILE* out, int32_t aIndent = 0);
|
void ListComputedStyles(FILE* out, int32_t aIndent = 0);
|
||||||
|
#endif
|
||||||
|
#if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
|
||||||
void ListStyleSheets(FILE* out, int32_t aIndent = 0);
|
void ListStyleSheets(FILE* out, int32_t aIndent = 0);
|
||||||
#endif // #ifdef DEBUG
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop all active elements (plugins and the caret) in this presentation and
|
* 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 GetResolution() const { return mResolution.valueOr(1.0); }
|
||||||
float GetCumulativeResolution();
|
float GetCumulativeResolution() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accessors for a flag that tracks whether the most recent change to
|
* 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; }
|
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
|
* Used by session restore code to restore a resolution before the first
|
||||||
* paint.
|
* paint.
|
||||||
@ -1664,6 +1652,8 @@ class PresShell final : public nsStubDocumentObserver,
|
|||||||
nsIFrame* GetDrawEventTargetFrame() { return mDrawEventTargetFrame; }
|
nsIFrame* GetDrawEventTargetFrame() { return mDrawEventTargetFrame; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool GetZoomableByAPZ() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~PresShell();
|
~PresShell();
|
||||||
|
|
||||||
@ -1894,13 +1884,8 @@ class PresShell final : public nsStubDocumentObserver,
|
|||||||
public:
|
public:
|
||||||
NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent, override)
|
NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent, override)
|
||||||
|
|
||||||
void Revoke() {
|
void Revoke();
|
||||||
if (mPresShell) {
|
|
||||||
mPresShell->GetPresContext()->RefreshDriver()->RemoveRefreshObserver(
|
|
||||||
this, FlushType::Display);
|
|
||||||
mPresShell = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void WillRefresh(TimeStamp aTime) override {
|
void WillRefresh(TimeStamp aTime) override {
|
||||||
if (mPresShell) {
|
if (mPresShell) {
|
||||||
@ -2906,10 +2891,10 @@ class PresShell final : public nsStubDocumentObserver,
|
|||||||
// the mouse pointer may have changed without the mouse moving (eg scrolling,
|
// the mouse pointer may have changed without the mouse moving (eg scrolling,
|
||||||
// change to the document contents).
|
// change to the document contents).
|
||||||
// It is set only on a presshell for a root document, this value represents
|
// 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
|
// the last observed location of the mouse relative to that root document,
|
||||||
// is set to (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if the mouse isn't
|
// in visual coordinates. It is set to (NS_UNCONSTRAINEDSIZE,
|
||||||
// over our window or there is no last observed mouse location for some
|
// NS_UNCONSTRAINEDSIZE) if the mouse isn't over our window or there is no
|
||||||
// reason.
|
// last observed mouse location for some reason.
|
||||||
nsPoint mMouseLocation;
|
nsPoint mMouseLocation;
|
||||||
// This is an APZ state variable that tracks the target guid for the last
|
// This is an APZ state variable that tracks the target guid for the last
|
||||||
// mouse event that was processed (corresponding to mMouseLocation). This is
|
// mouse event that was processed (corresponding to mMouseLocation). This is
|
||||||
|
@ -146,8 +146,6 @@ enum class ScrollFlags {
|
|||||||
|
|
||||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ScrollFlags)
|
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ScrollFlags)
|
||||||
|
|
||||||
enum class ScrollableDirection { Horizontal, Vertical, Either };
|
|
||||||
|
|
||||||
// See comment at declaration of RenderDocument() for the detail.
|
// See comment at declaration of RenderDocument() for the detail.
|
||||||
enum class RenderDocumentFlags {
|
enum class RenderDocumentFlags {
|
||||||
None = 0,
|
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/ComputedStyle.h"
|
||||||
#include "mozilla/ComputedStyleInlines.h"
|
#include "mozilla/ComputedStyleInlines.h"
|
||||||
#include "mozilla/DocumentStyleRootIterator.h"
|
#include "mozilla/DocumentStyleRootIterator.h"
|
||||||
|
#include "mozilla/EffectSet.h"
|
||||||
#include "mozilla/GeckoBindings.h"
|
#include "mozilla/GeckoBindings.h"
|
||||||
#include "mozilla/LayerAnimationInfo.h"
|
#include "mozilla/LayerAnimationInfo.h"
|
||||||
#include "mozilla/layers/AnimationInfo.h"
|
#include "mozilla/layers/AnimationInfo.h"
|
||||||
@ -18,8 +19,13 @@
|
|||||||
#include "mozilla/ServoBindings.h"
|
#include "mozilla/ServoBindings.h"
|
||||||
#include "mozilla/ServoStyleSetInlines.h"
|
#include "mozilla/ServoStyleSetInlines.h"
|
||||||
#include "mozilla/StaticPrefs_layout.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/Unused.h"
|
||||||
#include "mozilla/ViewportFrame.h"
|
#include "mozilla/ViewportFrame.h"
|
||||||
|
#include "mozilla/IntegerRange.h"
|
||||||
#include "mozilla/dom/ChildIterator.h"
|
#include "mozilla/dom/ChildIterator.h"
|
||||||
#include "mozilla/dom/DocumentInlines.h"
|
#include "mozilla/dom/DocumentInlines.h"
|
||||||
#include "mozilla/dom/ElementInlines.h"
|
#include "mozilla/dom/ElementInlines.h"
|
||||||
@ -43,12 +49,7 @@
|
|||||||
#include "nsStyleUtil.h"
|
#include "nsStyleUtil.h"
|
||||||
#include "nsTransitionManager.h"
|
#include "nsTransitionManager.h"
|
||||||
#include "StickyScrollContainer.h"
|
#include "StickyScrollContainer.h"
|
||||||
#include "mozilla/EffectSet.h"
|
|
||||||
#include "mozilla/IntegerRange.h"
|
|
||||||
#include "SVGObserverUtils.h"
|
|
||||||
#include "SVGTextFrame.h"
|
|
||||||
#include "ActiveLayerTracker.h"
|
#include "ActiveLayerTracker.h"
|
||||||
#include "nsSVGIntegrationUtils.h"
|
|
||||||
|
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
# include "nsAccessibilityService.h"
|
# include "nsAccessibilityService.h"
|
||||||
@ -465,11 +466,8 @@ static bool StateChangeMayAffectFrame(const Element& aElement,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool brokenChanged = aStates.HasAtLeastOneOfStates(
|
const bool brokenChanged = aStates.HasState(NS_EVENT_STATE_BROKEN);
|
||||||
NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED |
|
const bool loadingChanged = aStates.HasState(NS_EVENT_STATE_LOADING);
|
||||||
NS_EVENT_STATE_SUPPRESSED);
|
|
||||||
const bool loadingChanged =
|
|
||||||
aStates.HasAtLeastOneOfStates(NS_EVENT_STATE_LOADING);
|
|
||||||
|
|
||||||
if (!brokenChanged && !loadingChanged) {
|
if (!brokenChanged && !loadingChanged) {
|
||||||
return false;
|
return false;
|
||||||
@ -653,7 +651,7 @@ static nsIFrame* GetFrameForChildrenOnlyTransformHint(nsIFrame* aFrame) {
|
|||||||
if (aFrame->IsSVGOuterSVGFrame()) {
|
if (aFrame->IsSVGOuterSVGFrame()) {
|
||||||
aFrame = aFrame->PrincipalChildList().FirstChild();
|
aFrame = aFrame->PrincipalChildList().FirstChild();
|
||||||
MOZ_ASSERT(aFrame->IsSVGOuterSVGAnonChildFrame(),
|
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),
|
MOZ_ASSERT(aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer),
|
||||||
"Children-only transforms only expected on SVG frames");
|
"Children-only transforms only expected on SVG frames");
|
||||||
@ -693,9 +691,23 @@ static bool RecomputePosition(nsIFrame* aFrame) {
|
|||||||
return false;
|
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 (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();
|
nsIFrame* ph = aFrame->GetPlaceholderFrame();
|
||||||
if (ph && ph->HasAnyStateBits(PLACEHOLDER_STATICPOS_NEEDS_CSSALIGN)) {
|
if (ph && ph->HasAnyStateBits(PLACEHOLDER_STATICPOS_NEEDS_CSSALIGN)) {
|
||||||
return false;
|
return false;
|
||||||
@ -744,14 +756,11 @@ static bool RecomputePosition(nsIFrame* aFrame) {
|
|||||||
for (nsIFrame* cont = aFrame; cont;
|
for (nsIFrame* cont = aFrame; cont;
|
||||||
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
|
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
|
||||||
nsIFrame* cb = cont->GetContainingBlock();
|
nsIFrame* cb = cont->GetContainingBlock();
|
||||||
nsMargin newOffsets;
|
|
||||||
WritingMode wm = cb->GetWritingMode();
|
WritingMode wm = cb->GetWritingMode();
|
||||||
const LogicalSize size = cb->ContentSize();
|
const LogicalSize cbSize = cb->ContentSize();
|
||||||
|
const LogicalMargin newLogicalOffsets =
|
||||||
ReflowInput::ComputeRelativeOffsets(wm, cont, size, newOffsets);
|
ReflowInput::ComputeRelativeOffsets(wm, cont, cbSize);
|
||||||
NS_ASSERTION(newOffsets.left == -newOffsets.right &&
|
const nsMargin newOffsets = newLogicalOffsets.GetPhysicalMargin(wm);
|
||||||
newOffsets.top == -newOffsets.bottom,
|
|
||||||
"ComputeRelativeOffsets should return valid results");
|
|
||||||
|
|
||||||
// ReflowInput::ApplyRelativePositioning would work here, but
|
// ReflowInput::ApplyRelativePositioning would work here, but
|
||||||
// since we've already checked mPosition and aren't changing the frame's
|
// 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();
|
nsIFrame* cbFrame = parentFrame->GetContainingBlock();
|
||||||
if (cbFrame && (aFrame->GetContainingBlock() != parentFrame ||
|
if (cbFrame && (aFrame->GetContainingBlock() != parentFrame ||
|
||||||
parentFrame->IsTableFrame())) {
|
parentFrame->IsTableFrame())) {
|
||||||
|
const auto cbWM = cbFrame->GetWritingMode();
|
||||||
LogicalSize cbSize = cbFrame->GetLogicalSize();
|
LogicalSize cbSize = cbFrame->GetLogicalSize();
|
||||||
cbReflowInput.emplace(cbFrame->PresContext(), cbFrame, rc, cbSize);
|
cbReflowInput.emplace(cbFrame->PresContext(), cbFrame, rc, cbSize);
|
||||||
cbReflowInput->ComputedPhysicalMargin() = cbFrame->GetUsedMargin();
|
cbReflowInput->SetComputedLogicalMargin(
|
||||||
cbReflowInput->ComputedPhysicalPadding() = cbFrame->GetUsedPadding();
|
cbWM, cbFrame->GetLogicalUsedMargin(cbWM));
|
||||||
cbReflowInput->ComputedPhysicalBorderPadding() =
|
cbReflowInput->SetComputedLogicalPadding(
|
||||||
cbFrame->GetUsedBorderAndPadding();
|
cbWM, cbFrame->GetLogicalUsedPadding(cbWM));
|
||||||
|
cbReflowInput->SetComputedLogicalBorderPadding(
|
||||||
|
cbWM, cbFrame->GetLogicalUsedBorderAndPadding(cbWM));
|
||||||
parentReflowInput.mCBReflowInput = cbReflowInput.ptr();
|
parentReflowInput.mCBReflowInput = cbReflowInput.ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,11 +829,12 @@ static bool RecomputePosition(nsIFrame* aFrame) {
|
|||||||
"parentSize should be valid");
|
"parentSize should be valid");
|
||||||
parentReflowInput.SetComputedISize(std::max(parentSize.ISize(parentWM), 0));
|
parentReflowInput.SetComputedISize(std::max(parentSize.ISize(parentWM), 0));
|
||||||
parentReflowInput.SetComputedBSize(std::max(parentSize.BSize(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.SetComputedLogicalPadding(
|
||||||
parentReflowInput.ComputedPhysicalBorderPadding() =
|
parentWM, parentFrame->GetLogicalUsedPadding(parentWM));
|
||||||
parentFrame->GetUsedBorderAndPadding();
|
parentReflowInput.SetComputedLogicalBorderPadding(
|
||||||
|
parentWM, parentFrame->GetLogicalUsedBorderAndPadding(parentWM));
|
||||||
LogicalSize availSize = parentSize.ConvertTo(frameWM, parentWM);
|
LogicalSize availSize = parentSize.ConvertTo(frameWM, parentWM);
|
||||||
availSize.BSize(frameWM) = NS_UNCONSTRAINEDSIZE;
|
availSize.BSize(frameWM) = NS_UNCONSTRAINEDSIZE;
|
||||||
|
|
||||||
@ -839,11 +852,10 @@ static bool RecomputePosition(nsIFrame* aFrame) {
|
|||||||
availSize, Some(lcbSize));
|
availSize, Some(lcbSize));
|
||||||
nscoord computedISize = reflowInput.ComputedISize();
|
nscoord computedISize = reflowInput.ComputedISize();
|
||||||
nscoord computedBSize = reflowInput.ComputedBSize();
|
nscoord computedBSize = reflowInput.ComputedBSize();
|
||||||
computedISize +=
|
const auto frameBP = reflowInput.ComputedLogicalBorderPadding(frameWM);
|
||||||
reflowInput.ComputedLogicalBorderPadding().IStartEnd(frameWM);
|
computedISize += frameBP.IStartEnd(frameWM);
|
||||||
if (computedBSize != NS_UNCONSTRAINEDSIZE) {
|
if (computedBSize != NS_UNCONSTRAINEDSIZE) {
|
||||||
computedBSize +=
|
computedBSize += frameBP.BStartEnd(frameWM);
|
||||||
reflowInput.ComputedLogicalBorderPadding().BStartEnd(frameWM);
|
|
||||||
}
|
}
|
||||||
LogicalSize logicalSize = aFrame->GetLogicalSize(frameWM);
|
LogicalSize logicalSize = aFrame->GetLogicalSize(frameWM);
|
||||||
nsSize size = aFrame->GetSize();
|
nsSize size = aFrame->GetSize();
|
||||||
@ -860,26 +872,26 @@ static bool RecomputePosition(nsIFrame* aFrame) {
|
|||||||
// match the reflow code path.
|
// match the reflow code path.
|
||||||
//
|
//
|
||||||
// TODO(emilio): It'd be nice if this did logical math instead, but it seems
|
// 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.
|
// to me the math should work out on vertical writing modes as well. See Bug
|
||||||
if (NS_AUTOOFFSET == reflowInput.ComputedPhysicalOffsets().left) {
|
// 1675861 for some hints.
|
||||||
reflowInput.ComputedPhysicalOffsets().left =
|
const nsMargin offset = reflowInput.ComputedPhysicalOffsets();
|
||||||
cbSize.width - reflowInput.ComputedPhysicalOffsets().right -
|
const nsMargin margin = reflowInput.ComputedPhysicalMargin();
|
||||||
reflowInput.ComputedPhysicalMargin().right - size.width -
|
|
||||||
reflowInput.ComputedPhysicalMargin().left;
|
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) {
|
nscoord top = offset.top;
|
||||||
reflowInput.ComputedPhysicalOffsets().top =
|
if (top == NS_AUTOOFFSET) {
|
||||||
cbSize.height - reflowInput.ComputedPhysicalOffsets().bottom -
|
top = cbSize.height - offset.bottom - margin.bottom - size.height -
|
||||||
reflowInput.ComputedPhysicalMargin().bottom - size.height -
|
margin.top;
|
||||||
reflowInput.ComputedPhysicalMargin().top;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the frame
|
// Move the frame
|
||||||
nsPoint pos(parentBorder.left + reflowInput.ComputedPhysicalOffsets().left +
|
nsPoint pos(parentBorder.left + left + margin.left,
|
||||||
reflowInput.ComputedPhysicalMargin().left,
|
parentBorder.top + top + margin.top);
|
||||||
parentBorder.top + reflowInput.ComputedPhysicalOffsets().top +
|
|
||||||
reflowInput.ComputedPhysicalMargin().top);
|
|
||||||
aFrame->SetPosition(pos);
|
aFrame->SetPosition(pos);
|
||||||
|
|
||||||
if (aFrame->IsInScrollAnchorChain()) {
|
if (aFrame->IsInScrollAnchorChain()) {
|
||||||
@ -928,7 +940,7 @@ static bool ContainingBlockChangeAffectsDescendants(
|
|||||||
nsIFrame* outOfFlow = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
|
nsIFrame* outOfFlow = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
|
||||||
// If SVG text frames could appear here, they could confuse us since
|
// If SVG text frames could appear here, they could confuse us since
|
||||||
// they ignore their position style ... but they can't.
|
// 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");
|
"SVG text frames can't be out of flow");
|
||||||
auto* display = outOfFlow->StyleDisplay();
|
auto* display = outOfFlow->StyleDisplay();
|
||||||
if (display->IsAbsolutelyPositionedStyle()) {
|
if (display->IsAbsolutelyPositionedStyle()) {
|
||||||
@ -1028,7 +1040,7 @@ static void DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
|||||||
aFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
aFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||||
!aFrame->IsSVGOuterSVGFrame()) {
|
!aFrame->IsSVGOuterSVGFrame()) {
|
||||||
// Need to update our overflow rects:
|
// Need to update our overflow rects:
|
||||||
nsSVGUtils::ScheduleReflowSVG(aFrame);
|
SVGUtils::ScheduleReflowSVG(aFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
ActiveLayerTracker::NotifyNeedsRepaint(aFrame);
|
ActiveLayerTracker::NotifyNeedsRepaint(aFrame);
|
||||||
@ -1039,7 +1051,7 @@ static void DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
|||||||
needInvalidatingPaint = true;
|
needInvalidatingPaint = true;
|
||||||
|
|
||||||
ActiveLayerTracker::NotifyRestyle(aFrame, eCSSProperty_opacity);
|
ActiveLayerTracker::NotifyRestyle(aFrame, eCSSProperty_opacity);
|
||||||
if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
|
if (SVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
|
||||||
// SVG effects paints the opacity without using
|
// SVG effects paints the opacity without using
|
||||||
// nsDisplayOpacity. We need to invalidate manually.
|
// nsDisplayOpacity. We need to invalidate manually.
|
||||||
aFrame->InvalidateFrameSubtree();
|
aFrame->InvalidateFrameSubtree();
|
||||||
@ -1559,9 +1571,9 @@ void RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList) {
|
|||||||
// opacity layer change hint when we do opacity optimization for SVG.
|
// opacity layer change hint when we do opacity optimization for SVG.
|
||||||
// We can't do it in nsStyleEffects::CalcDifference() just like we do
|
// 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
|
// 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) &&
|
if ((hint & nsChangeHint_UpdateOpacityLayer) &&
|
||||||
nsSVGUtils::CanOptimizeOpacity(frame)) {
|
SVGUtils::CanOptimizeOpacity(frame)) {
|
||||||
hint &= ~nsChangeHint_UpdateOpacityLayer;
|
hint &= ~nsChangeHint_UpdateOpacityLayer;
|
||||||
hint |= nsChangeHint_RepaintFrame;
|
hint |= nsChangeHint_RepaintFrame;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "nsCSSRendering.h"
|
#include "nsCSSRendering.h"
|
||||||
#include "nsMargin.h"
|
#include "nsMargin.h"
|
||||||
#include "nsStyleStruct.h"
|
#include "nsStyleStruct.h"
|
||||||
#include "SVGContentUtils.h"
|
#include "mozilla/SVGContentUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
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/dom/EventTarget.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsView.h"
|
#include "nsView.h"
|
||||||
#include "PositionedEventTargeting.h"
|
#include "PositionedEventTargeting.h"
|
||||||
|
|
||||||
@ -107,15 +108,6 @@ nsIFrame* TouchManager::SetupTarget(WidgetTouchEvent* aEvent,
|
|||||||
return aFrame;
|
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;
|
nsIFrame* target = aFrame;
|
||||||
for (int32_t i = aEvent->mTouches.Length(); i;) {
|
for (int32_t i = aEvent->mTouches.Length(); i;) {
|
||||||
--i;
|
--i;
|
||||||
@ -124,9 +116,10 @@ nsIFrame* TouchManager::SetupTarget(WidgetTouchEvent* aEvent,
|
|||||||
int32_t id = touch->Identifier();
|
int32_t id = touch->Identifier();
|
||||||
if (!TouchManager::HasCapturedTouch(id)) {
|
if (!TouchManager::HasCapturedTouch(id)) {
|
||||||
// find the target for this touch
|
// find the target for this touch
|
||||||
|
RelativeTo relativeTo{aFrame};
|
||||||
nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
||||||
aEvent, touch->mRefPoint, aFrame);
|
aEvent, touch->mRefPoint, relativeTo);
|
||||||
target = FindFrameTargetedByInputEvent(aEvent, aFrame, eventPoint, flags);
|
target = FindFrameTargetedByInputEvent(aEvent, relativeTo, eventPoint);
|
||||||
if (target) {
|
if (target) {
|
||||||
nsCOMPtr<nsIContent> targetContent;
|
nsCOMPtr<nsIContent> targetContent;
|
||||||
target->GetContentForEvent(aEvent, getter_AddRefs(targetContent));
|
target->GetContentForEvent(aEvent, getter_AddRefs(targetContent));
|
||||||
|
@ -136,7 +136,7 @@ Maybe<gfx::IntRectTyped<TargetUnits>> ViewAs(
|
|||||||
}
|
}
|
||||||
return Nothing();
|
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
|
// target matrix type, rather than its source and target unit types, as
|
||||||
// the explicit template argument, so an example invocation is:
|
// the explicit template argument, so an example invocation is:
|
||||||
// ViewAs<ScreenToLayerMatrix4x4>(otherTypedMatrix, justification)
|
// ViewAs<ScreenToLayerMatrix4x4>(otherTypedMatrix, justification)
|
||||||
@ -150,6 +150,28 @@ TargetMatrix ViewAs(const gfx::Matrix4x4Typed<SourceMatrixSourceUnits,
|
|||||||
PixelCastJustification) {
|
PixelCastJustification) {
|
||||||
return TargetMatrix::FromUnknownMatrix(aMatrix.ToUnknownMatrix());
|
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.
|
// Convenience functions for casting untyped entities to typed entities.
|
||||||
// Using these functions does not require a justification, but once we convert
|
// Using these functions does not require a justification, but once we convert
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#ifndef MOZ_UNITS_H_
|
#ifndef MOZ_UNITS_H_
|
||||||
#define MOZ_UNITS_H_
|
#define MOZ_UNITS_H_
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "mozilla/gfx/Coord.h"
|
#include "mozilla/gfx/Coord.h"
|
||||||
#include "mozilla/gfx/Point.h"
|
#include "mozilla/gfx/Point.h"
|
||||||
#include "mozilla/gfx/Rect.h"
|
#include "mozilla/gfx/Rect.h"
|
||||||
@ -15,12 +17,11 @@
|
|||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
#include "nsRegion.h"
|
#include "nsRegion.h"
|
||||||
#include "mozilla/AppUnits.h"
|
#include "mozilla/AppUnits.h"
|
||||||
#include "mozilla/TypeTraits.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsPixel : FalseType {};
|
struct IsPixel : std::false_type {};
|
||||||
|
|
||||||
// See struct declaration for a description of each unit type.
|
// See struct declaration for a description of each unit type.
|
||||||
struct CSSPixel;
|
struct CSSPixel;
|
||||||
@ -34,23 +35,23 @@ struct DesktopPixel;
|
|||||||
struct ImagePixel;
|
struct ImagePixel;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<CSSPixel> : TrueType {};
|
struct IsPixel<CSSPixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<LayoutDevicePixel> : TrueType {};
|
struct IsPixel<LayoutDevicePixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<LayerPixel> : TrueType {};
|
struct IsPixel<LayerPixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<CSSTransformedLayerPixel> : TrueType {};
|
struct IsPixel<CSSTransformedLayerPixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<RenderTargetPixel> : TrueType {};
|
struct IsPixel<RenderTargetPixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<ImagePixel> : TrueType {};
|
struct IsPixel<ImagePixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<ScreenPixel> : TrueType {};
|
struct IsPixel<ScreenPixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<ParentLayerPixel> : TrueType {};
|
struct IsPixel<ParentLayerPixel> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct IsPixel<DesktopPixel> : TrueType {};
|
struct IsPixel<DesktopPixel> : std::true_type {};
|
||||||
|
|
||||||
typedef gfx::CoordTyped<CSSPixel> CSSCoord;
|
typedef gfx::CoordTyped<CSSPixel> CSSCoord;
|
||||||
typedef gfx::IntCoordTyped<CSSPixel> CSSIntCoord;
|
typedef gfx::IntCoordTyped<CSSPixel> CSSIntCoord;
|
||||||
@ -221,8 +222,13 @@ typedef gfx::ScaleFactors2D<ParentLayerPixel, ScreenPixel>
|
|||||||
typedef gfx::ScaleFactors2D<ParentLayerPixel, ParentLayerPixel>
|
typedef gfx::ScaleFactors2D<ParentLayerPixel, ParentLayerPixel>
|
||||||
ParentLayerToParentLayerScale2D;
|
ParentLayerToParentLayerScale2D;
|
||||||
|
|
||||||
|
typedef gfx::Matrix4x4Typed<CSSPixel, CSSPixel> CSSToCSSMatrix4x4;
|
||||||
typedef gfx::Matrix4x4Typed<LayoutDevicePixel, LayoutDevicePixel>
|
typedef gfx::Matrix4x4Typed<LayoutDevicePixel, LayoutDevicePixel>
|
||||||
LayoutDeviceToLayoutDeviceMatrix4x4;
|
LayoutDeviceToLayoutDeviceMatrix4x4;
|
||||||
|
#ifdef MOZ_BUILD_WEBRENDER
|
||||||
|
typedef gfx::Matrix4x4Typed<LayoutDevicePixel, ParentLayerPixel>
|
||||||
|
LayoutDeviceToParentLayerMatrix4x4;
|
||||||
|
#endif
|
||||||
typedef gfx::Matrix4x4Typed<LayerPixel, ParentLayerPixel>
|
typedef gfx::Matrix4x4Typed<LayerPixel, ParentLayerPixel>
|
||||||
LayerToParentLayerMatrix4x4;
|
LayerToParentLayerMatrix4x4;
|
||||||
typedef gfx::Matrix4x4Typed<LayerPixel, ScreenPixel> LayerToScreenMatrix4x4;
|
typedef gfx::Matrix4x4Typed<LayerPixel, ScreenPixel> LayerToScreenMatrix4x4;
|
||||||
@ -822,6 +828,11 @@ struct CoordOfImpl<gfx::IntRectTyped<Units>> {
|
|||||||
typedef gfx::IntCoordTyped<Units> Type;
|
typedef gfx::IntCoordTyped<Units> Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Units>
|
||||||
|
struct CoordOfImpl<gfx::SizeTyped<Units>> {
|
||||||
|
typedef gfx::CoordTyped<Units> Type;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using CoordOf = typename CoordOfImpl<T>::Type;
|
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 "Units.h"
|
||||||
#include "UnitTransforms.h"
|
#include "UnitTransforms.h"
|
||||||
|
|
||||||
#define ZCC_LOG(...)
|
static mozilla::LazyLogModule sApzZoomLog("apz.zoom");
|
||||||
// #define ZCC_LOG(...) printf_stderr("ZCC: " __VA_ARGS__)
|
#define ZCC_LOG(...) MOZ_LOG(sApzZoomLog, LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(ZoomConstraintsClient, nsIDOMEventListener, nsIObserver)
|
NS_IMPL_ISUPPORTS(ZoomConstraintsClient, nsIDOMEventListener, nsIObserver)
|
||||||
|
|
||||||
#define DOM_META_ADDED NS_LITERAL_STRING("DOMMetaAdded")
|
#define DOM_META_ADDED u"DOMMetaAdded"_ns
|
||||||
#define DOM_META_CHANGED NS_LITERAL_STRING("DOMMetaChanged")
|
#define DOM_META_CHANGED u"DOMMetaChanged"_ns
|
||||||
#define FULLSCREEN_CHANGED NS_LITERAL_STRING("fullscreenchange")
|
#define FULLSCREEN_CHANGED u"fullscreenchange"_ns
|
||||||
#define BEFORE_FIRST_PAINT NS_LITERAL_CSTRING("before-first-paint")
|
#define BEFORE_FIRST_PAINT "before-first-paint"_ns
|
||||||
#define NS_PREF_CHANGED NS_LITERAL_CSTRING("nsPref:changed")
|
#define NS_PREF_CHANGED "nsPref:changed"_ns
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
using namespace mozilla::layers;
|
using namespace mozilla::layers;
|
||||||
|
|
||||||
ZoomConstraintsClient::ZoomConstraintsClient()
|
ZoomConstraintsClient::ZoomConstraintsClient()
|
||||||
: mDocument(nullptr), mPresShell(nullptr) {}
|
: mDocument(nullptr),
|
||||||
|
mPresShell(nullptr),
|
||||||
|
mZoomConstraints(false, false, CSSToParentLayerScale(1.f),
|
||||||
|
CSSToParentLayerScale(1.f)) {}
|
||||||
|
|
||||||
ZoomConstraintsClient::~ZoomConstraintsClient() = default;
|
ZoomConstraintsClient::~ZoomConstraintsClient() = default;
|
||||||
|
|
||||||
@ -184,6 +187,9 @@ static mozilla::layers::ZoomConstraints ComputeZoomConstraintsFromViewportInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ZoomConstraintsClient::RefreshZoomConstraints() {
|
void ZoomConstraintsClient::RefreshZoomConstraints() {
|
||||||
|
mZoomConstraints = ZoomConstraints(false, false, CSSToParentLayerScale(1.f),
|
||||||
|
CSSToParentLayerScale(1.f));
|
||||||
|
|
||||||
nsIWidget* widget = GetWidget(mPresShell);
|
nsIWidget* widget = GetWidget(mPresShell);
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
return;
|
return;
|
||||||
@ -207,22 +213,22 @@ void ZoomConstraintsClient::RefreshZoomConstraints() {
|
|||||||
nsViewportInfo viewportInfo = mDocument->GetViewportInfo(ViewAs<ScreenPixel>(
|
nsViewportInfo viewportInfo = mDocument->GetViewportInfo(ViewAs<ScreenPixel>(
|
||||||
screenSize, PixelCastJustification::LayoutDeviceIsScreenForBounds));
|
screenSize, PixelCastJustification::LayoutDeviceIsScreenForBounds));
|
||||||
|
|
||||||
mozilla::layers::ZoomConstraints zoomConstraints =
|
mZoomConstraints =
|
||||||
ComputeZoomConstraintsFromViewportInfo(viewportInfo, mDocument);
|
ComputeZoomConstraintsFromViewportInfo(viewportInfo, mDocument);
|
||||||
|
|
||||||
if (mDocument->Fullscreen()) {
|
if (mDocument->Fullscreen()) {
|
||||||
ZCC_LOG("%p is in fullscreen, disallowing zooming\n", this);
|
ZCC_LOG("%p is in fullscreen, disallowing zooming\n", this);
|
||||||
zoomConstraints.mAllowZoom = false;
|
mZoomConstraints.mAllowZoom = false;
|
||||||
zoomConstraints.mAllowDoubleTapZoom = false;
|
mZoomConstraints.mAllowDoubleTapZoom = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zoomConstraints.mAllowDoubleTapZoom) {
|
if (mZoomConstraints.mAllowDoubleTapZoom) {
|
||||||
// If the CSS viewport is narrower than the screen (i.e. width <=
|
// If the CSS viewport is narrower than the screen (i.e. width <=
|
||||||
// device-width) then we disable double-tap-to-zoom behaviour.
|
// device-width) then we disable double-tap-to-zoom behaviour.
|
||||||
CSSToLayoutDeviceScale scale =
|
CSSToLayoutDeviceScale scale =
|
||||||
mPresShell->GetPresContext()->CSSToDevPixelScale();
|
mPresShell->GetPresContext()->CSSToDevPixelScale();
|
||||||
if ((viewportInfo.GetSize() * scale).width <= screenSize.width) {
|
if ((viewportInfo.GetSize() * scale).width <= screenSize.width) {
|
||||||
zoomConstraints.mAllowDoubleTapZoom = false;
|
mZoomConstraints.mAllowDoubleTapZoom = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +238,8 @@ void ZoomConstraintsClient::RefreshZoomConstraints() {
|
|||||||
if (nsIScrollableFrame* rcdrsf =
|
if (nsIScrollableFrame* rcdrsf =
|
||||||
mPresShell->GetRootScrollFrameAsScrollable()) {
|
mPresShell->GetRootScrollFrameAsScrollable()) {
|
||||||
ZCC_LOG("Notifying RCD-RSF that it is zoomable: %d\n",
|
ZCC_LOG("Notifying RCD-RSF that it is zoomable: %d\n",
|
||||||
zoomConstraints.mAllowZoom);
|
mZoomConstraints.mAllowZoom);
|
||||||
rcdrsf->SetZoomableByAPZ(zoomConstraints.mAllowZoom);
|
rcdrsf->SetZoomableByAPZ(mZoomConstraints.mAllowZoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollableLayerGuid newGuid(LayersId{0}, presShellId, viewId);
|
ScrollableLayerGuid newGuid(LayersId{0}, presShellId, viewId);
|
||||||
@ -246,6 +252,6 @@ void ZoomConstraintsClient::RefreshZoomConstraints() {
|
|||||||
}
|
}
|
||||||
mGuid = Some(newGuid);
|
mGuid = Some(newGuid);
|
||||||
ZCC_LOG("Sending constraints %s in %p for { %u, %" PRIu64 " }\n",
|
ZCC_LOG("Sending constraints %s in %p for { %u, %" PRIu64 " }\n",
|
||||||
Stringify(zoomConstraints).c_str(), this, presShellId, viewId);
|
Stringify(mZoomConstraints).c_str(), this, presShellId, viewId);
|
||||||
widget->UpdateZoomConstraints(presShellId, viewId, Some(zoomConstraints));
|
widget->UpdateZoomConstraints(presShellId, viewId, Some(mZoomConstraints));
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#ifndef ZoomConstraintsClient_h_
|
#ifndef ZoomConstraintsClient_h_
|
||||||
#define ZoomConstraintsClient_h_
|
#define ZoomConstraintsClient_h_
|
||||||
|
|
||||||
#include "mozilla/dom/Document.h"
|
|
||||||
#include "mozilla/layers/ScrollableLayerGuid.h"
|
#include "mozilla/layers/ScrollableLayerGuid.h"
|
||||||
|
#include "mozilla/layers/ZoomConstraints.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIDOMEventListener.h"
|
#include "nsIDOMEventListener.h"
|
||||||
@ -37,6 +37,8 @@ class ZoomConstraintsClient final : public nsIDOMEventListener,
|
|||||||
void Destroy();
|
void Destroy();
|
||||||
void ScreenSizeChanged();
|
void ScreenSizeChanged();
|
||||||
|
|
||||||
|
bool GetAllowZoom() const { return mZoomConstraints.mAllowZoom; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RefreshZoomConstraints();
|
void RefreshZoomConstraints();
|
||||||
|
|
||||||
@ -45,6 +47,7 @@ class ZoomConstraintsClient final : public nsIDOMEventListener,
|
|||||||
mozilla::PresShell* MOZ_NON_OWNING_REF mPresShell;
|
mozilla::PresShell* MOZ_NON_OWNING_REF mPresShell;
|
||||||
nsCOMPtr<mozilla::dom::EventTarget> mEventTarget;
|
nsCOMPtr<mozilla::dom::EventTarget> mEventTarget;
|
||||||
mozilla::Maybe<mozilla::layers::ScrollableLayerGuid> mGuid;
|
mozilla::Maybe<mozilla::layers::ScrollableLayerGuid> mGuid;
|
||||||
|
mozilla::layers::ZoomConstraints mZoomConstraints;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#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 413587-1.svg
|
||||||
load 414058-1.html
|
load 414058-1.html
|
||||||
load 415503.xhtml
|
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
|
HTTP load 419985.html
|
||||||
load 420031-1.html
|
load 420031-1.html
|
||||||
load 420213-1.html
|
load 420213-1.html
|
||||||
@ -401,7 +401,7 @@ load 709536-1.xhtml
|
|||||||
load 722137.html
|
load 722137.html
|
||||||
load 725535.html
|
load 725535.html
|
||||||
load 727601.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
|
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 736924-1.html
|
||||||
load 749816-1.html
|
load 749816-1.html
|
||||||
@ -482,7 +482,7 @@ load 1308848-2.html
|
|||||||
load 1338772-1.html
|
load 1338772-1.html
|
||||||
load 1340571.html
|
load 1340571.html
|
||||||
pref(dom.animations-api.implicit-keyframes.enabled,true) load 1343139-1.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 1343937.html
|
||||||
load 1352380.html
|
load 1352380.html
|
||||||
load 1362423-1.html
|
load 1362423-1.html
|
||||||
@ -511,6 +511,7 @@ load 1414303.html
|
|||||||
load 1419762.html
|
load 1419762.html
|
||||||
load 1419802.html
|
load 1419802.html
|
||||||
load 1420533.html
|
load 1420533.html
|
||||||
|
load 1422908.html
|
||||||
load 1423216.html
|
load 1423216.html
|
||||||
load 1425893.html
|
load 1425893.html
|
||||||
load 1425959.html
|
load 1425959.html
|
||||||
@ -587,3 +588,4 @@ load 1586600.html
|
|||||||
load 1599518.html
|
load 1599518.html
|
||||||
load 1599532.html
|
load 1599532.html
|
||||||
pref(layout.accessiblecaret.enabled,true) load 1606492.html
|
pref(layout.accessiblecaret.enabled,true) load 1606492.html
|
||||||
|
load 1690163.html
|
||||||
|
@ -58,6 +58,7 @@ EXPORTS += [
|
|||||||
'nsPresContextInlines.h',
|
'nsPresContextInlines.h',
|
||||||
'nsQuoteList.h',
|
'nsQuoteList.h',
|
||||||
'nsRefreshDriver.h',
|
'nsRefreshDriver.h',
|
||||||
|
'nsRefreshObservers.h',
|
||||||
'nsStyleChangeList.h',
|
'nsStyleChangeList.h',
|
||||||
'nsStyleSheetService.h',
|
'nsStyleSheetService.h',
|
||||||
'StackArena.h',
|
'StackArena.h',
|
||||||
@ -71,25 +72,31 @@ EXPORTS += [
|
|||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
'AccessibleCaretEventHub.h',
|
'AccessibleCaretEventHub.h',
|
||||||
'ArenaObjectID.h',
|
'ArenaObjectID.h',
|
||||||
|
'DisplayPortUtils.h',
|
||||||
'GeckoMVMContext.h',
|
'GeckoMVMContext.h',
|
||||||
'GeometryUtils.h',
|
'GeometryUtils.h',
|
||||||
'MotionPathUtils.h',
|
'MotionPathUtils.h',
|
||||||
'MVMContext.h',
|
'MVMContext.h',
|
||||||
'OverflowChangedTracker.h',
|
'OverflowChangedTracker.h',
|
||||||
|
'PositionedEventTargeting.h',
|
||||||
'PresShell.h',
|
'PresShell.h',
|
||||||
'PresShellForwards.h',
|
'PresShellForwards.h',
|
||||||
'PresShellInlines.h',
|
'PresShellInlines.h',
|
||||||
|
'RelativeTo.h',
|
||||||
'RestyleManager.h',
|
'RestyleManager.h',
|
||||||
'ScrollStyles.h',
|
'ScrollStyles.h',
|
||||||
'ScrollTypes.h',
|
'ScrollTypes.h',
|
||||||
'ShapeUtils.h',
|
'ShapeUtils.h',
|
||||||
'StaticPresData.h',
|
'StaticPresData.h',
|
||||||
|
'SurfaceFromElementResult.h',
|
||||||
|
'ViewportUtils.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'AccessibleCaret.cpp',
|
'AccessibleCaret.cpp',
|
||||||
'AccessibleCaretEventHub.cpp',
|
'AccessibleCaretEventHub.cpp',
|
||||||
'AccessibleCaretManager.cpp',
|
'AccessibleCaretManager.cpp',
|
||||||
|
'DisplayPortUtils.cpp',
|
||||||
'GeckoMVMContext.cpp',
|
'GeckoMVMContext.cpp',
|
||||||
'GeometryUtils.cpp',
|
'GeometryUtils.cpp',
|
||||||
'LayoutLogging.cpp',
|
'LayoutLogging.cpp',
|
||||||
@ -121,6 +128,7 @@ UNIFIED_SOURCES += [
|
|||||||
'StackArena.cpp',
|
'StackArena.cpp',
|
||||||
'StaticPresData.cpp',
|
'StaticPresData.cpp',
|
||||||
'TouchManager.cpp',
|
'TouchManager.cpp',
|
||||||
|
'ViewportUtils.cpp',
|
||||||
'ZoomConstraintsClient.cpp',
|
'ZoomConstraintsClient.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -141,7 +149,6 @@ LOCAL_INCLUDES += [
|
|||||||
'../painting',
|
'../painting',
|
||||||
'../printing',
|
'../printing',
|
||||||
'../style',
|
'../style',
|
||||||
'../svg',
|
|
||||||
'../tables',
|
'../tables',
|
||||||
'../xul',
|
'../xul',
|
||||||
'../xul/tree/',
|
'../xul/tree/',
|
||||||
|
@ -74,8 +74,8 @@ static bool IsIsolateControl(char16_t aChar) {
|
|||||||
// Returns 0 if no override control character is implied by this style.
|
// Returns 0 if no override control character is implied by this style.
|
||||||
static char16_t GetBidiOverride(ComputedStyle* aComputedStyle) {
|
static char16_t GetBidiOverride(ComputedStyle* aComputedStyle) {
|
||||||
const nsStyleVisibility* vis = aComputedStyle->StyleVisibility();
|
const nsStyleVisibility* vis = aComputedStyle->StyleVisibility();
|
||||||
if ((vis->mWritingMode == NS_STYLE_WRITING_MODE_VERTICAL_RL ||
|
if ((vis->mWritingMode == StyleWritingModeProperty::VerticalRl ||
|
||||||
vis->mWritingMode == NS_STYLE_WRITING_MODE_VERTICAL_LR) &&
|
vis->mWritingMode == StyleWritingModeProperty::VerticalLr) &&
|
||||||
vis->mTextOrientation == StyleTextOrientation::Upright) {
|
vis->mTextOrientation == StyleTextOrientation::Upright) {
|
||||||
return kLRO;
|
return kLRO;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/PresShellInlines.h"
|
#include "mozilla/PresShellInlines.h"
|
||||||
|
#include "mozilla/PrintedSheetFrame.h"
|
||||||
#include "mozilla/ServoBindings.h"
|
#include "mozilla/ServoBindings.h"
|
||||||
#include "mozilla/ServoStyleSetInlines.h"
|
#include "mozilla/ServoStyleSetInlines.h"
|
||||||
#include "mozilla/StaticPrefs_layout.h"
|
#include "mozilla/StaticPrefs_layout.h"
|
||||||
@ -118,8 +119,11 @@
|
|||||||
#undef NOISY_FIRST_LETTER
|
#undef NOISY_FIRST_LETTER
|
||||||
|
|
||||||
#include "nsMathMLParts.h"
|
#include "nsMathMLParts.h"
|
||||||
|
#include "mozilla/dom/SVGAnimationElement.h"
|
||||||
|
#include "mozilla/dom/SVGFilters.h"
|
||||||
#include "mozilla/dom/SVGTests.h"
|
#include "mozilla/dom/SVGTests.h"
|
||||||
#include "nsSVGUtils.h"
|
#include "mozilla/SVGGradientFrame.h"
|
||||||
|
#include "mozilla/SVGUtils.h"
|
||||||
|
|
||||||
#include "nsRefreshDriver.h"
|
#include "nsRefreshDriver.h"
|
||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
@ -353,7 +357,7 @@ static inline bool IsDisplayContents(const nsIContent* aContent) {
|
|||||||
*/
|
*/
|
||||||
static bool IsFrameForSVG(const nsIFrame* aFrame) {
|
static bool IsFrameForSVG(const nsIFrame* aFrame) {
|
||||||
return aFrame->IsFrameOfType(nsIFrame::eSVG) ||
|
return aFrame->IsFrameOfType(nsIFrame::eSVG) ||
|
||||||
nsSVGUtils::IsInSVGTextSubtree(aFrame);
|
SVGUtils::IsInSVGTextSubtree(aFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsLastContinuationForColumnContent(const nsIFrame* aFrame) {
|
static bool IsLastContinuationForColumnContent(const nsIFrame* aFrame) {
|
||||||
@ -712,6 +716,10 @@ class MOZ_STACK_CLASS nsFrameConstructorState {
|
|||||||
// mode).
|
// mode).
|
||||||
bool mCreatingExtraFrames;
|
bool mCreatingExtraFrames;
|
||||||
|
|
||||||
|
// This keeps track of whether we have found a "rendered legend" for
|
||||||
|
// the current FieldSetFrame.
|
||||||
|
bool mHasRenderedLegend;
|
||||||
|
|
||||||
nsTArray<RefPtr<nsIContent>> mGeneratedContentWithInitializer;
|
nsTArray<RefPtr<nsIContent>> mGeneratedContentWithInitializer;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
@ -907,6 +915,7 @@ nsFrameConstructorState::nsFrameConstructorState(
|
|||||||
mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
|
mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
|
||||||
mHavePendingPopupgroup(false),
|
mHavePendingPopupgroup(false),
|
||||||
mCreatingExtraFrames(false),
|
mCreatingExtraFrames(false),
|
||||||
|
mHasRenderedLegend(false),
|
||||||
mCurrentPendingBindingInsertionPoint(nullptr) {
|
mCurrentPendingBindingInsertionPoint(nullptr) {
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
nsIPopupContainer* popupContainer =
|
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.
|
// float to "none"? That's OK per CSS 2.1, as far as I can tell.
|
||||||
|
|
||||||
if (aContentParentFrame &&
|
if (aContentParentFrame &&
|
||||||
nsSVGUtils::IsInSVGTextSubtree(aContentParentFrame)) {
|
SVGUtils::IsInSVGTextSubtree(aContentParentFrame)) {
|
||||||
return aContentParentFrame;
|
return aContentParentFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1105,13 +1114,13 @@ AbsoluteFrameList* nsFrameConstructorState::GetOutOfFlowFrameList(
|
|||||||
return &mPopupList;
|
return &mPopupList;
|
||||||
}
|
}
|
||||||
#endif // MOZ_XUL
|
#endif // MOZ_XUL
|
||||||
if (aCanBeFloated && aNewFrame->IsFloating()) {
|
const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
|
||||||
|
if (aCanBeFloated && disp->IsFloatingStyle()) {
|
||||||
*aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
|
*aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
|
||||||
return &mFloatedList;
|
return &mFloatedList;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aCanBePositioned) {
|
if (aCanBePositioned) {
|
||||||
const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
|
|
||||||
if (disp->mTopLayer != StyleTopLayer::None) {
|
if (disp->mTopLayer != StyleTopLayer::None) {
|
||||||
*aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
|
*aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
|
||||||
if (disp->mPosition == StylePositionProperty::Fixed) {
|
if (disp->mPosition == StylePositionProperty::Fixed) {
|
||||||
@ -1439,7 +1448,7 @@ static bool ShouldCreateImageFrameForContent(const Element& aElement,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Span<const StyleContentItem> items = content.AsItems().AsSpan();
|
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;
|
const Type type = item.tag;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Url:
|
case Type::Image:
|
||||||
return GeneratedImageContent::Create(*mDocument, aContentIndex);
|
return GeneratedImageContent::Create(*mDocument, aContentIndex);
|
||||||
|
|
||||||
case Type::String:
|
case Type::String:
|
||||||
@ -1613,8 +1622,7 @@ already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGeneratedContent(
|
|||||||
|
|
||||||
auto initializer = MakeUnique<nsGenConInitializer>(
|
auto initializer = MakeUnique<nsGenConInitializer>(
|
||||||
std::move(node), counterList, &nsCSSFrameConstructor::CountersDirty);
|
std::move(node), counterList, &nsCSSFrameConstructor::CountersDirty);
|
||||||
return CreateGenConTextNode(aState, EmptyString(),
|
return CreateGenConTextNode(aState, u""_ns, std::move(initializer));
|
||||||
std::move(initializer));
|
|
||||||
}
|
}
|
||||||
case Type::OpenQuote:
|
case Type::OpenQuote:
|
||||||
case Type::CloseQuote:
|
case Type::CloseQuote:
|
||||||
@ -1623,8 +1631,7 @@ already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGeneratedContent(
|
|||||||
auto node = MakeUnique<nsQuoteNode>(type, aContentIndex);
|
auto node = MakeUnique<nsQuoteNode>(type, aContentIndex);
|
||||||
auto initializer = MakeUnique<nsGenConInitializer>(
|
auto initializer = MakeUnique<nsGenConInitializer>(
|
||||||
std::move(node), &mQuoteList, &nsCSSFrameConstructor::QuotesDirty);
|
std::move(node), &mQuoteList, &nsCSSFrameConstructor::QuotesDirty);
|
||||||
return CreateGenConTextNode(aState, EmptyString(),
|
return CreateGenConTextNode(aState, u""_ns, std::move(initializer));
|
||||||
std::move(initializer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type::MozAltContent: {
|
case Type::MozAltContent: {
|
||||||
@ -2552,7 +2559,7 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
|
|||||||
ViewportFrame [fixed-cb]
|
ViewportFrame [fixed-cb]
|
||||||
nsHTMLScrollFrame
|
nsHTMLScrollFrame
|
||||||
nsCanvasFrame [abs-cb]
|
nsCanvasFrame [abs-cb]
|
||||||
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
|
root element frame (nsBlockFrame, SVGOuterSVGFrame,
|
||||||
nsTableWrapperFrame, nsPlaceholderFrame)
|
nsTableWrapperFrame, nsPlaceholderFrame)
|
||||||
|
|
||||||
Galley presentation, XUL
|
Galley presentation, XUL
|
||||||
@ -2565,22 +2572,24 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
|
|||||||
|
|
||||||
ViewportFrame
|
ViewportFrame
|
||||||
nsPageSequenceFrame
|
nsPageSequenceFrame
|
||||||
nsPageFrame
|
PrintedSheetFrame
|
||||||
nsPageContentFrame [fixed-cb]
|
nsPageFrame
|
||||||
nsCanvasFrame [abs-cb]
|
nsPageContentFrame [fixed-cb]
|
||||||
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
|
nsCanvasFrame [abs-cb]
|
||||||
nsTableWrapperFrame, nsPlaceholderFrame)
|
root element frame (nsBlockFrame, SVGOuterSVGFrame,
|
||||||
|
nsTableWrapperFrame, nsPlaceholderFrame)
|
||||||
|
|
||||||
Print-preview presentation, non-XUL
|
Print-preview presentation, non-XUL
|
||||||
|
|
||||||
ViewportFrame
|
ViewportFrame
|
||||||
nsHTMLScrollFrame
|
nsHTMLScrollFrame
|
||||||
nsPageSequenceFrame
|
nsPageSequenceFrame
|
||||||
nsPageFrame
|
PrintedSheetFrame
|
||||||
nsPageContentFrame [fixed-cb]
|
nsPageFrame
|
||||||
nsCanvasFrame [abs-cb]
|
nsPageContentFrame [fixed-cb]
|
||||||
root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
|
nsCanvasFrame [abs-cb]
|
||||||
nsTableWrapperFrame, nsPlaceholderFrame)
|
root element frame (nsBlockFrame, SVGOuterSVGFrame,
|
||||||
|
nsTableWrapperFrame, nsPlaceholderFrame)
|
||||||
|
|
||||||
Print/print preview of XUL is not supported.
|
Print/print preview of XUL is not supported.
|
||||||
[fixed-cb]: the default containing block for fixed-pos content
|
[fixed-cb]: the default containing block for fixed-pos content
|
||||||
@ -2634,7 +2643,6 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
|
|||||||
rootFrame = mPageSequenceFrame =
|
rootFrame = mPageSequenceFrame =
|
||||||
NS_NewPageSequenceFrame(mPresShell, viewportPseudoStyle);
|
NS_NewPageSequenceFrame(mPresShell, viewportPseudoStyle);
|
||||||
rootPseudo = PseudoStyleType::pageSequence;
|
rootPseudo = PseudoStyleType::pageSequence;
|
||||||
rootFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
|
// --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
|
||||||
@ -2716,13 +2724,19 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPaginated) {
|
if (isPaginated) {
|
||||||
// Create the first page
|
// Create the first printed sheet frame, as the sole child (for now) of our
|
||||||
// Set the initial child lists
|
// 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* canvasFrame;
|
||||||
nsContainerFrame* pageFrame =
|
nsContainerFrame* pageFrame =
|
||||||
ConstructPageFrame(mPresShell, rootFrame, nullptr, canvasFrame);
|
ConstructPageFrame(mPresShell, printedSheetFrame, nullptr, canvasFrame);
|
||||||
pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
|
pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
|
||||||
SetInitialSingleChild(rootFrame, pageFrame);
|
SetInitialSingleChild(printedSheetFrame, pageFrame);
|
||||||
|
|
||||||
// The eventual parent of the document element frame.
|
// The eventual parent of the document element frame.
|
||||||
// XXX should this be set for every new page (in ConstructPageFrame)?
|
// XXX should this be set for every new page (in ConstructPageFrame)?
|
||||||
@ -2759,15 +2773,28 @@ void nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(
|
|||||||
aFrameList);
|
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(
|
nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
|
||||||
PresShell* aPresShell, nsContainerFrame* aParentFrame,
|
PresShell* aPresShell, nsContainerFrame* aParentFrame,
|
||||||
nsIFrame* aPrevPageFrame, nsContainerFrame*& aCanvasFrame) {
|
nsIFrame* aPrevPageFrame, nsContainerFrame*& aCanvasFrame) {
|
||||||
ComputedStyle* parentComputedStyle = aParentFrame->Style();
|
|
||||||
ServoStyleSet* styleSet = aPresShell->StyleSet();
|
ServoStyleSet* styleSet = aPresShell->StyleSet();
|
||||||
|
|
||||||
RefPtr<ComputedStyle> pagePseudoStyle;
|
RefPtr<ComputedStyle> pagePseudoStyle =
|
||||||
pagePseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
|
styleSet->ResolveNonInheritingAnonymousBoxStyle(PseudoStyleType::page);
|
||||||
PseudoStyleType::page, parentComputedStyle);
|
|
||||||
|
|
||||||
nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
|
nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
|
||||||
|
|
||||||
@ -2776,8 +2803,8 @@ nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
|
|||||||
pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
|
pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
|
||||||
|
|
||||||
RefPtr<ComputedStyle> pageContentPseudoStyle;
|
RefPtr<ComputedStyle> pageContentPseudoStyle;
|
||||||
pageContentPseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
|
pageContentPseudoStyle = styleSet->ResolveNonInheritingAnonymousBoxStyle(
|
||||||
PseudoStyleType::pageContent, pagePseudoStyle);
|
PseudoStyleType::pageContent);
|
||||||
|
|
||||||
nsContainerFrame* pageContentFrame =
|
nsContainerFrame* pageContentFrame =
|
||||||
NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
|
NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
|
||||||
@ -2791,6 +2818,8 @@ nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
|
|||||||
}
|
}
|
||||||
pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
|
pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
|
||||||
if (!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);
|
pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
|
||||||
}
|
}
|
||||||
SetInitialSingleChild(pageFrame, pageContentFrame);
|
SetInitialSingleChild(pageFrame, pageContentFrame);
|
||||||
@ -3061,11 +3090,6 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
|
|||||||
PseudoStyleType::scrolledContent, false, scrollFrame);
|
PseudoStyleType::scrolledContent, false, scrollFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsContainerFrame* absPosContainer = nullptr;
|
|
||||||
if (fieldsetFrame->IsAbsPosContainingBlock()) {
|
|
||||||
absPosContainer = fieldsetFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the inner ::-moz-fieldset-content frame.
|
// Create the inner ::-moz-fieldset-content frame.
|
||||||
nsContainerFrame* contentFrameTop;
|
nsContainerFrame* contentFrameTop;
|
||||||
nsContainerFrame* contentFrame;
|
nsContainerFrame* contentFrame;
|
||||||
@ -3092,9 +3116,6 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
|
|||||||
if (fieldsetContentStyle->StyleColumn()->IsColumnContainerStyle()) {
|
if (fieldsetContentStyle->StyleColumn()->IsColumnContainerStyle()) {
|
||||||
contentFrameTop = BeginBuildingColumns(
|
contentFrameTop = BeginBuildingColumns(
|
||||||
aState, content, parent, contentFrame, fieldsetContentStyle);
|
aState, content, parent, contentFrame, fieldsetContentStyle);
|
||||||
if (absPosContainer) {
|
|
||||||
absPosContainer = contentFrameTop;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// No need to create column container. Initialize content frame.
|
// No need to create column container. Initialize content frame.
|
||||||
InitAndRestoreFrame(aState, content, parent, contentFrame);
|
InitAndRestoreFrame(aState, content, parent, contentFrame);
|
||||||
@ -3112,40 +3133,21 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
|
|||||||
nsFrameList childList;
|
nsFrameList childList;
|
||||||
|
|
||||||
contentFrameTop->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
contentFrameTop->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
||||||
if (absPosContainer) {
|
if (fieldsetFrame->IsAbsPosContainingBlock()) {
|
||||||
aState.PushAbsoluteContainingBlock(contentFrameTop, absPosContainer,
|
aState.PushAbsoluteContainingBlock(contentFrameTop, fieldsetFrame,
|
||||||
absoluteSaveState);
|
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;
|
nsFrameList fieldsetKids;
|
||||||
fieldsetKids.AppendFrame(nullptr,
|
fieldsetKids.AppendFrame(nullptr,
|
||||||
scrollFrame ? scrollFrame : contentFrameTop);
|
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)) {
|
if (!MayNeedToCreateColumnSpanSiblings(contentFrame, childList)) {
|
||||||
// Set the inner frame's initial child lists.
|
// Set the inner frame's initial child lists.
|
||||||
contentFrame->SetInitialChildList(kPrincipalList, childList);
|
contentFrame->SetInitialChildList(kPrincipalList, childList);
|
||||||
@ -3171,10 +3173,10 @@ nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
|
|||||||
FinishBuildingScrollFrame(scrollFrame, contentFrameTop);
|
FinishBuildingScrollFrame(scrollFrame, contentFrameTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the outer frame's initial child list
|
// We use AppendFrames here because the rendered legend will already
|
||||||
fieldsetFrame->SetInitialChildList(kPrincipalList, fieldsetKids);
|
// 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;
|
return fieldsetFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3267,9 +3269,8 @@ const nsCSSFrameConstructor::FrameConstructionData*
|
|||||||
nsCSSFrameConstructor::FindTextData(const Text& aTextContent,
|
nsCSSFrameConstructor::FindTextData(const Text& aTextContent,
|
||||||
nsIFrame* aParentFrame) {
|
nsIFrame* aParentFrame) {
|
||||||
if (aParentFrame && IsFrameForSVG(aParentFrame)) {
|
if (aParentFrame && IsFrameForSVG(aParentFrame)) {
|
||||||
nsIFrame* ancestorFrame =
|
nsIFrame* ancestorFrame = SVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
|
||||||
nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
|
if (!ancestorFrame || !SVGUtils::IsInSVGTextSubtree(ancestorFrame)) {
|
||||||
if (!ancestorFrame || !nsSVGUtils::IsInSVGTextSubtree(ancestorFrame)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3382,15 +3383,15 @@ nsCSSFrameConstructor::FindDataByTag(const Element& aElement,
|
|||||||
#define COMPLEX_TAG_CREATE(_tag, _func) \
|
#define COMPLEX_TAG_CREATE(_tag, _func) \
|
||||||
{ nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
|
{ nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
|
||||||
|
|
||||||
static bool IsFrameForFieldSet(nsIFrame* aFrame) {
|
static nsFieldSetFrame* GetFieldSetFrameFor(nsIFrame* aFrame) {
|
||||||
auto pseudo = aFrame->Style()->GetPseudoType();
|
auto pseudo = aFrame->Style()->GetPseudoType();
|
||||||
if (pseudo == PseudoStyleType::fieldsetContent ||
|
if (pseudo == PseudoStyleType::fieldsetContent ||
|
||||||
pseudo == PseudoStyleType::scrolledContent ||
|
pseudo == PseudoStyleType::scrolledContent ||
|
||||||
pseudo == PseudoStyleType::columnSet ||
|
pseudo == PseudoStyleType::columnSet ||
|
||||||
pseudo == PseudoStyleType::columnContent) {
|
pseudo == PseudoStyleType::columnContent) {
|
||||||
return IsFrameForFieldSet(aFrame->GetParent());
|
return GetFieldSetFrameFor(aFrame->GetParent());
|
||||||
}
|
}
|
||||||
return aFrame->IsFieldSetFrame();
|
return do_QueryFrame(aFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
@ -3399,25 +3400,11 @@ nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
|
|||||||
nsIFrame* aParentFrame,
|
nsIFrame* aParentFrame,
|
||||||
ComputedStyle& aStyle) {
|
ComputedStyle& aStyle) {
|
||||||
MOZ_ASSERT(aElement.IsHTMLElement());
|
MOZ_ASSERT(aElement.IsHTMLElement());
|
||||||
|
|
||||||
nsAtom* tag = aElement.NodeInfo()->NameAtom();
|
|
||||||
NS_ASSERTION(!aParentFrame ||
|
NS_ASSERTION(!aParentFrame ||
|
||||||
aParentFrame->Style()->GetPseudoType() !=
|
aParentFrame->Style()->GetPseudoType() !=
|
||||||
PseudoStyleType::fieldsetContent ||
|
PseudoStyleType::fieldsetContent ||
|
||||||
aParentFrame->GetParent()->IsFieldSetFrame(),
|
aParentFrame->GetParent()->IsFieldSetFrame(),
|
||||||
"Unexpected parent for fieldset content anon box");
|
"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[] = {
|
static const FrameConstructionDataByTag sHTMLData[] = {
|
||||||
SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData),
|
SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData),
|
||||||
SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
|
SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
|
||||||
@ -3433,9 +3420,6 @@ nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
|
|||||||
SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
|
SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
|
||||||
COMPLEX_TAG_CREATE(fieldset,
|
COMPLEX_TAG_CREATE(fieldset,
|
||||||
&nsCSSFrameConstructor::ConstructFieldSetFrame),
|
&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(frameset, NS_NewHTMLFramesetFrame),
|
||||||
SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
|
SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
|
||||||
{nsGkAtoms::button,
|
{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
|
// cases when the object is broken/suppressed/etc (e.g. a broken image), but
|
||||||
// we want to treat those cases as TYPE_NULL
|
// we want to treat those cases as TYPE_NULL
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
if (aElement.State().HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
|
if (aElement.State().HasState(NS_EVENT_STATE_BROKEN)) {
|
||||||
NS_EVENT_STATE_USERDISABLED |
|
|
||||||
NS_EVENT_STATE_SUPPRESSED)) {
|
|
||||||
type = nsIObjectLoadingContent::TYPE_NULL;
|
type = nsIObjectLoadingContent::TYPE_NULL;
|
||||||
} else {
|
} else {
|
||||||
nsCOMPtr<nsIObjectLoadingContent> objContent =
|
nsCOMPtr<nsIObjectLoadingContent> objContent =
|
||||||
@ -4028,26 +4010,6 @@ nsresult nsCSSFrameConstructor::GetAnonymousContent(
|
|||||||
return NS_OK;
|
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.
|
// XUL frames are not allowed to be out of flow.
|
||||||
#define SIMPLE_XUL_FCDATA(_func) \
|
#define SIMPLE_XUL_FCDATA(_func) \
|
||||||
FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH, _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
|
# ifdef MOZ_THUNDERBIRD
|
||||||
if (aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
|
if (aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
|
||||||
NS_LITERAL_STRING("menu-button"), eCaseMatters)) {
|
u"menu-button"_ns, eCaseMatters)) {
|
||||||
return &sXULMenuData;
|
return &sXULMenuData;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
@ -4234,10 +4196,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::BeginBuildingScrollFrame(
|
|||||||
if (!gfxScrollFrame) {
|
if (!gfxScrollFrame) {
|
||||||
// Build a XULScrollFrame when the child is a box, otherwise an
|
// Build a XULScrollFrame when the child is a box, otherwise an
|
||||||
// HTMLScrollFrame
|
// HTMLScrollFrame
|
||||||
// XXXbz this is the lone remaining consumer of IsXULDisplayType.
|
|
||||||
// I wonder whether we can eliminate that somehow.
|
|
||||||
const nsStyleDisplay* displayStyle = aContentStyle->StyleDisplay();
|
const nsStyleDisplay* displayStyle = aContentStyle->StyleDisplay();
|
||||||
if (IsXULDisplayType(displayStyle)) {
|
if (displayStyle->IsXULDisplayStyle()) {
|
||||||
gfxScrollFrame = NS_NewXULScrollFrame(
|
gfxScrollFrame = NS_NewXULScrollFrame(
|
||||||
mPresShell, contentStyle, aIsRoot,
|
mPresShell, contentStyle, aIsRoot,
|
||||||
displayStyle->mDisplay == StyleDisplay::MozStack);
|
displayStyle->mDisplay == StyleDisplay::MozStack);
|
||||||
@ -4351,7 +4311,7 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
|
|||||||
// block-level.
|
// block-level.
|
||||||
NS_ASSERTION(
|
NS_ASSERTION(
|
||||||
!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) ||
|
!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) ||
|
||||||
aDisplay.IsBlockOutsideStyle() || IsXULDisplayType(&aDisplay),
|
aDisplay.IsBlockOutsideStyle() || aDisplay.IsXULDisplayStyle(),
|
||||||
"Style system did not apply CSS2.1 section 9.7 fixups");
|
"Style system did not apply CSS2.1 section 9.7 fixups");
|
||||||
|
|
||||||
// If this is "body", try propagating its scroll style to the viewport
|
// If this is "body", try propagating its scroll style to the viewport
|
||||||
@ -4665,7 +4625,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructNonScrollableBlockWithConstructor(
|
|||||||
if ((aDisplay->IsAbsolutelyPositionedStyle() || aDisplay->IsFloatingStyle() ||
|
if ((aDisplay->IsAbsolutelyPositionedStyle() || aDisplay->IsFloatingStyle() ||
|
||||||
aDisplay->DisplayInside() == StyleDisplayInside::FlowRoot ||
|
aDisplay->DisplayInside() == StyleDisplayInside::FlowRoot ||
|
||||||
clipPaginatedOverflow) &&
|
clipPaginatedOverflow) &&
|
||||||
!nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
|
!SVGUtils::IsInSVGTextSubtree(aParentFrame)) {
|
||||||
flags = NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS;
|
flags = NS_BLOCK_FORMATTING_CONTEXT_STATE_BITS;
|
||||||
if (clipPaginatedOverflow) {
|
if (clipPaginatedOverflow) {
|
||||||
flags |= NS_BLOCK_CLIP_PAGINATED_OVERFLOW;
|
flags |= NS_BLOCK_CLIP_PAGINATED_OVERFLOW;
|
||||||
@ -4990,17 +4950,18 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We don't need frames for animation elements
|
// 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;
|
return &sSuppressData;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag == nsGkAtoms::svg && !parentIsSVG) {
|
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
|
// of whether they fail conditional processing attributes, since various
|
||||||
// SVG frames assume that one exists. We handle the non-rendering
|
// SVG frames assume that one exists. We handle the non-rendering
|
||||||
// of failing outer <svg> element contents like <switch> statements,
|
// of failing outer <svg> element contents like <switch> statements,
|
||||||
// and do the PassesConditionalProcessingTests call in
|
// and do the PassesConditionalProcessingTests call in
|
||||||
// nsSVGOuterSVGFrame::Init.
|
// SVGOuterSVGFrame::Init.
|
||||||
static const FrameConstructionData sOuterSVGData =
|
static const FrameConstructionData sOuterSVGData =
|
||||||
FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructOuterSVG);
|
FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructOuterSVG);
|
||||||
return &sOuterSVGData;
|
return &sOuterSVGData;
|
||||||
@ -5016,7 +4977,7 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
|
|||||||
if (tests && !tests->PassesConditionalProcessingTests()) {
|
if (tests && !tests->PassesConditionalProcessingTests()) {
|
||||||
// Elements with failing conditional processing attributes never get
|
// Elements with failing conditional processing attributes never get
|
||||||
// rendered. Note that this is not where we select which frame in a
|
// 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) {
|
if (aIsWithinSVGText) {
|
||||||
// SVGTextFrame doesn't handle conditional processing attributes,
|
// SVGTextFrame doesn't handle conditional processing attributes,
|
||||||
// so don't create frames for descendants of <text> with failing
|
// so don't create frames for descendants of <text> with failing
|
||||||
@ -5024,7 +4985,7 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
|
|||||||
// is correct.
|
// is correct.
|
||||||
return &sSuppressData;
|
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,
|
// frame that doesn't render) so that paint servers can still be referenced,
|
||||||
// even if they live inside an element with failing conditional processing
|
// even if they live inside an element with failing conditional processing
|
||||||
// attributes.
|
// attributes.
|
||||||
@ -5033,9 +4994,8 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
|
|||||||
|
|
||||||
// Ensure that a stop frame is a child of a gradient and that gradients
|
// Ensure that a stop frame is a child of a gradient and that gradients
|
||||||
// can only have stop children.
|
// can only have stop children.
|
||||||
bool parentIsGradient =
|
bool parentIsGradient = aParentFrame && static_cast<SVGGradientFrame*>(
|
||||||
aParentFrame && (aParentFrame->IsSVGLinearGradientFrame() ||
|
do_QueryFrame(aParentFrame));
|
||||||
aParentFrame->IsSVGRadialGradientFrame());
|
|
||||||
bool stop = (tag == nsGkAtoms::stop);
|
bool stop = (tag == nsGkAtoms::stop);
|
||||||
if ((parentIsGradient && !stop) || (!parentIsGradient && stop)) {
|
if ((parentIsGradient && !stop) || (!parentIsGradient && stop)) {
|
||||||
return &sSuppressData;
|
return &sSuppressData;
|
||||||
@ -5045,7 +5005,8 @@ nsCSSFrameConstructor::FindSVGData(const Element& aElement,
|
|||||||
// primitives. If aParentFrame is null, we know that the frame that will
|
// 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.
|
// be created will be an nsInlineFrame, so it can never be a filter.
|
||||||
bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
|
bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
|
||||||
bool filterPrimitive = aElement.IsNodeOfType(nsINode::eFILTER);
|
nsCOMPtr<SVGFE> filterPrimitive =
|
||||||
|
do_QueryInterface(const_cast<Element*>(&aElement));
|
||||||
if ((parentIsFilter && !filterPrimitive) ||
|
if ((parentIsFilter && !filterPrimitive) ||
|
||||||
(!parentIsFilter && filterPrimitive)) {
|
(!parentIsFilter && filterPrimitive)) {
|
||||||
return &sSuppressData;
|
return &sSuppressData;
|
||||||
@ -5215,7 +5176,7 @@ void nsCSSFrameConstructor::DoAddFrameConstructionItems(
|
|||||||
ItemFlags aFlags) {
|
ItemFlags aFlags) {
|
||||||
auto flags = aFlags + ItemFlag::AllowPageBreak;
|
auto flags = aFlags + ItemFlag::AllowPageBreak;
|
||||||
if (aParentFrame) {
|
if (aParentFrame) {
|
||||||
if (nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
|
if (SVGUtils::IsInSVGTextSubtree(aParentFrame)) {
|
||||||
flags += ItemFlag::IsWithinSVGText;
|
flags += ItemFlag::IsWithinSVGText;
|
||||||
}
|
}
|
||||||
if (aParentFrame->IsBlockFrame() && aParentFrame->GetParent() &&
|
if (aParentFrame->IsBlockFrame() && aParentFrame->GetParent() &&
|
||||||
@ -5250,10 +5211,18 @@ void nsCSSFrameConstructor::AddFrameConstructionItems(
|
|||||||
static bool ShouldSuppressFrameInSelect(const nsIContent* aParent,
|
static bool ShouldSuppressFrameInSelect(const nsIContent* aParent,
|
||||||
const nsIContent& aChild) {
|
const nsIContent& aChild) {
|
||||||
if (!aParent ||
|
if (!aParent ||
|
||||||
!aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup)) {
|
!aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup,
|
||||||
|
nsGkAtoms::option)) {
|
||||||
return false;
|
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.
|
// 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
|
// 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;
|
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();
|
const auto& display = *aStyle.StyleDisplay();
|
||||||
return FindDisplayData(display, aElement);
|
return FindDisplayData(display, aElement);
|
||||||
}
|
}
|
||||||
@ -5518,6 +5498,16 @@ void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
|
|||||||
return;
|
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 =
|
const FrameConstructionData* data =
|
||||||
FindDataForContent(*aContent, *aComputedStyle, aParentFrame, aFlags);
|
FindDataForContent(*aContent, *aComputedStyle, aParentFrame, aFlags);
|
||||||
if (!data || data->mBits & FCDATA_SUPPRESS_FRAME) {
|
if (!data || data->mBits & FCDATA_SUPPRESS_FRAME) {
|
||||||
@ -5572,6 +5562,9 @@ void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
|
|||||||
item = aItems.AppendItem(this, data, aContent, pendingBinding,
|
item = aItems.AppendItem(this, data, aContent, pendingBinding,
|
||||||
do_AddRef(aComputedStyle),
|
do_AddRef(aComputedStyle),
|
||||||
aSuppressWhiteSpaceOptimizations);
|
aSuppressWhiteSpaceOptimizations);
|
||||||
|
if (aFlags.contains(ItemFlag::IsForRenderedLegend)) {
|
||||||
|
item->mIsRenderedLegend = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
item->mIsText = !aContent->IsElement();
|
item->mIsText = !aContent->IsElement();
|
||||||
item->mIsGeneratedContent = isGeneratedContent;
|
item->mIsGeneratedContent = isGeneratedContent;
|
||||||
@ -6124,20 +6117,6 @@ bool nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
|
|||||||
// below.
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6225,6 +6204,10 @@ nsIFrame* nsCSSFrameConstructor::AdjustSiblingFrame(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aSibling->IsRenderedLegend()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (aSibling->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
|
if (aSibling->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
|
||||||
aSibling = aSibling->GetPlaceholderFrame();
|
aSibling = aSibling->GetPlaceholderFrame();
|
||||||
MOZ_ASSERT(aSibling);
|
MOZ_ASSERT(aSibling);
|
||||||
@ -7163,7 +7146,14 @@ void nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
|
|||||||
// fieldsets have multiple insertion points.
|
// fieldsets have multiple insertion points.
|
||||||
NS_ASSERTION(isSingleInsert || frameType != LayoutFrameType::FieldSet,
|
NS_ASSERTION(isSingleInsert || frameType != LayoutFrameType::FieldSet,
|
||||||
"Unexpected parent");
|
"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) {
|
aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
|
||||||
// Just reframe the parent, since figuring out whether this
|
// Just reframe the parent, since figuring out whether this
|
||||||
// should be the new legend and then handling it is too complex.
|
// 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");
|
"no support for fragmenting table captions yet");
|
||||||
newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
|
newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
|
||||||
newFrame->Init(content, aParentFrame, aFrame);
|
newFrame->Init(content, aParentFrame, aFrame);
|
||||||
|
} else if (LayoutFrameType::PrintedSheet == frameType) {
|
||||||
|
newFrame = ConstructPrintedSheetFrame(mPresShell, aParentFrame, aFrame);
|
||||||
} else if (LayoutFrameType::Page == frameType) {
|
} else if (LayoutFrameType::Page == frameType) {
|
||||||
nsContainerFrame* canvasFrame;
|
nsContainerFrame* canvasFrame; // (unused outparam for ConstructPageFrame)
|
||||||
newFrame =
|
newFrame =
|
||||||
ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
|
ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
|
||||||
} else if (LayoutFrameType::TableWrapper == frameType) {
|
} else if (LayoutFrameType::TableWrapper == frameType) {
|
||||||
@ -8167,9 +8159,6 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
|
|||||||
} else if (LayoutFrameType::FieldSet == frameType) {
|
} else if (LayoutFrameType::FieldSet == frameType) {
|
||||||
newFrame = NS_NewFieldSetFrame(mPresShell, computedStyle);
|
newFrame = NS_NewFieldSetFrame(mPresShell, computedStyle);
|
||||||
newFrame->Init(content, aParentFrame, aFrame);
|
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) {
|
} else if (LayoutFrameType::FlexContainer == frameType) {
|
||||||
newFrame = NS_NewFlexContainerFrame(mPresShell, computedStyle);
|
newFrame = NS_NewFlexContainerFrame(mPresShell, computedStyle);
|
||||||
newFrame->Init(content, aParentFrame, aFrame);
|
newFrame->Init(content, aParentFrame, aFrame);
|
||||||
@ -8428,12 +8417,9 @@ bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame();
|
if (inFlowFrame->IsRenderedLegend()) {
|
||||||
if (insertionFrame && insertionFrame->IsLegendFrame() &&
|
|
||||||
aFrame->GetParent()->IsFieldSetFrame()) {
|
|
||||||
TRACE("Fieldset / Legend");
|
TRACE("Fieldset / Legend");
|
||||||
RecreateFramesForContent(aFrame->GetParent()->GetContent(),
|
RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
|
||||||
InsertionKind::Async);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9545,6 +9531,36 @@ inline void nsCSSFrameConstructor::ConstructFramesFromItemList(
|
|||||||
// that information offhand in many cases.
|
// that information offhand in many cases.
|
||||||
MOZ_ASSERT(ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox);
|
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);
|
CreateNeededPseudoContainers(aState, aItems, aParentFrame);
|
||||||
CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
|
CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
|
||||||
CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
|
CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
|
||||||
@ -9552,6 +9568,9 @@ inline void nsCSSFrameConstructor::ConstructFramesFromItemList(
|
|||||||
|
|
||||||
bool listItemListIsDirty = false;
|
bool listItemListIsDirty = false;
|
||||||
for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
|
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),
|
NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
|
||||||
"Needed pseudos didn't get created; expect bad things");
|
"Needed pseudos didn't get created; expect bad things");
|
||||||
// display:list-item boxes affects the start value of the "list-item"
|
// display:list-item boxes affects the start value of the "list-item"
|
||||||
@ -10136,7 +10155,7 @@ void nsCSSFrameConstructor::CreateLetterFrame(
|
|||||||
const nsStyleDisplay* display = sc->StyleDisplay();
|
const nsStyleDisplay* display = sc->StyleDisplay();
|
||||||
nsFirstLetterFrame* letterFrame;
|
nsFirstLetterFrame* letterFrame;
|
||||||
if (display->IsFloatingStyle() &&
|
if (display->IsFloatingStyle() &&
|
||||||
!nsSVGUtils::IsInSVGTextSubtree(aParentFrame)) {
|
!SVGUtils::IsInSVGTextSubtree(aParentFrame)) {
|
||||||
// Make a floating first-letter frame
|
// Make a floating first-letter frame
|
||||||
letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
|
letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
|
||||||
aParentFrame, parentComputedStyle,
|
aParentFrame, parentComputedStyle,
|
||||||
@ -11618,6 +11637,30 @@ bool nsCSSFrameConstructor::WipeContainingBlock(
|
|||||||
// that is not part of an {ib} split, but should become an {ib} split.
|
// 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
|
// 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/while with breaks to take us to the "go and reconstruct" code.
|
||||||
do {
|
do {
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
struct nsStyleDisplay;
|
struct nsStyleDisplay;
|
||||||
struct nsGenConInitializer;
|
struct nsGenConInitializer;
|
||||||
|
|
||||||
|
class nsBlockFrame;
|
||||||
class nsContainerFrame;
|
class nsContainerFrame;
|
||||||
class nsFirstLineFrame;
|
class nsFirstLineFrame;
|
||||||
class nsFirstLetterFrame;
|
class nsFirstLetterFrame;
|
||||||
@ -43,6 +44,7 @@ namespace mozilla {
|
|||||||
|
|
||||||
class ComputedStyle;
|
class ComputedStyle;
|
||||||
class PresShell;
|
class PresShell;
|
||||||
|
class PrintedSheetFrame;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
@ -365,6 +367,10 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
nsContainerFrame* aRootElementFrame, nsFrameConstructorState&,
|
nsContainerFrame* aRootElementFrame, nsFrameConstructorState&,
|
||||||
nsFrameList&);
|
nsFrameList&);
|
||||||
|
|
||||||
|
mozilla::PrintedSheetFrame* ConstructPrintedSheetFrame(
|
||||||
|
PresShell* aPresShell, nsContainerFrame* aParentFrame,
|
||||||
|
nsIFrame* aPrevSheetFrame);
|
||||||
|
|
||||||
nsContainerFrame* ConstructPageFrame(PresShell* aPresShell,
|
nsContainerFrame* ConstructPageFrame(PresShell* aPresShell,
|
||||||
nsContainerFrame* aParentFrame,
|
nsContainerFrame* aParentFrame,
|
||||||
nsIFrame* aPrevPageFrame,
|
nsIFrame* aPrevPageFrame,
|
||||||
@ -386,6 +392,8 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
AllowTextPathChild,
|
AllowTextPathChild,
|
||||||
// The item is content created by an nsIAnonymousContentCreator frame.
|
// The item is content created by an nsIAnonymousContentCreator frame.
|
||||||
IsAnonymousContentCreatorContent,
|
IsAnonymousContentCreatorContent,
|
||||||
|
// The item will be the rendered legend of a <fieldset>.
|
||||||
|
IsForRenderedLegend,
|
||||||
};
|
};
|
||||||
|
|
||||||
using ItemFlags = mozilla::EnumSet<ItemFlag>;
|
using ItemFlags = mozilla::EnumSet<ItemFlag>;
|
||||||
@ -1118,7 +1126,8 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
mIsAllInline(false),
|
mIsAllInline(false),
|
||||||
mIsBlock(false),
|
mIsBlock(false),
|
||||||
mIsPopup(false),
|
mIsPopup(false),
|
||||||
mIsLineParticipant(false) {
|
mIsLineParticipant(false),
|
||||||
|
mIsRenderedLegend(false) {
|
||||||
MOZ_COUNT_CTOR(FrameConstructionItem);
|
MOZ_COUNT_CTOR(FrameConstructionItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1201,6 +1210,8 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
bool mIsPopup : 1;
|
bool mIsPopup : 1;
|
||||||
// Whether this item should be treated as a line participant
|
// Whether this item should be treated as a line participant
|
||||||
bool mIsLineParticipant : 1;
|
bool mIsLineParticipant : 1;
|
||||||
|
// Whether this item is the rendered legend of a <fieldset>
|
||||||
|
bool mIsRenderedLegend : 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Not allocated from the general heap - instead, use the new/Delete APIs
|
// 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);
|
mozilla::PseudoStyleType aInnerPseudo, bool aCandidateRootFrame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an nsSVGOuterSVGFrame.
|
* Construct an SVGOuterSVGFrame.
|
||||||
*/
|
*/
|
||||||
nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
|
nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
|
||||||
FrameConstructionItem& aItem,
|
FrameConstructionItem& aItem,
|
||||||
@ -1525,7 +1536,7 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
nsFrameList& aFrameList);
|
nsFrameList& aFrameList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an nsSVGMarkerFrame.
|
* Construct an SVGMarkerFrame.
|
||||||
*/
|
*/
|
||||||
nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
|
nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
|
||||||
FrameConstructionItem& aItem,
|
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.
|
// then snap it back, put it as close to the edge as it can.
|
||||||
if (vertical) {
|
if (vertical) {
|
||||||
nscoord overflow = caretInScroll.YMost() -
|
nscoord overflow = caretInScroll.YMost() -
|
||||||
scrolled->GetVisualOverflowRectRelativeToSelf().height;
|
scrolled->InkOverflowRectRelativeToSelf().height;
|
||||||
if (overflow > 0) {
|
if (overflow > 0) {
|
||||||
rect.y -= overflow;
|
rect.y -= overflow;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nscoord overflow = caretInScroll.XMost() -
|
nscoord overflow = caretInScroll.XMost() -
|
||||||
scrolled->GetVisualOverflowRectRelativeToSelf().width;
|
scrolled->InkOverflowRectRelativeToSelf().width;
|
||||||
if (overflow > 0) {
|
if (overflow > 0) {
|
||||||
rect.x -= overflow;
|
rect.x -= overflow;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,12 @@
|
|||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/IntegerRange.h"
|
#include "mozilla/IntegerRange.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/StaticPrefs_layout.h"
|
||||||
#include "mozilla/WritingModes.h"
|
#include "mozilla/WritingModes.h"
|
||||||
#include "nsBulletFrame.h" // legacy location for list style type to text code
|
#include "nsBulletFrame.h" // legacy location for list style type to text code
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
|
#include "nsContainerFrame.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "mozilla/dom/Text.h"
|
#include "mozilla/dom/Text.h"
|
||||||
|
|
||||||
@ -126,6 +128,42 @@ void nsCounterList::SetScope(nsCounterNode* aNode) {
|
|||||||
return;
|
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*,
|
// Get the content node for aNode's rendering object's *parent*,
|
||||||
// since scope includes siblings, so we want a descendant check on
|
// since scope includes siblings, so we want a descendant check on
|
||||||
// parents.
|
// parents.
|
||||||
@ -155,6 +193,7 @@ void nsCounterList::SetScope(nsCounterNode* aNode) {
|
|||||||
nodeContent == startContent) &&
|
nodeContent == startContent) &&
|
||||||
// everything is inside the root (except the case above,
|
// everything is inside the root (except the case above,
|
||||||
// a second reset on the root)
|
// a second reset on the root)
|
||||||
|
// FIXME(bug 1477524): should use flattened tree here:
|
||||||
(!startContent || nodeContent->IsInclusiveDescendantOf(startContent))) {
|
(!startContent || nodeContent->IsInclusiveDescendantOf(startContent))) {
|
||||||
aNode->mScopeStart = start;
|
aNode->mScopeStart = start;
|
||||||
aNode->mScopePrev = prev;
|
aNode->mScopePrev = prev;
|
||||||
@ -249,8 +288,10 @@ bool nsCounterManager::AddCounterChanges(nsIFrame* aFrame) {
|
|||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
for (const auto& pair : styleContent->mCounterIncrement.AsSpan()) {
|
for (const auto& pair : styleContent->mCounterIncrement.AsSpan()) {
|
||||||
hasListItemIncrement |= pair.name.AsAtom() == nsGkAtoms::list_item;
|
hasListItemIncrement |= pair.name.AsAtom() == nsGkAtoms::list_item;
|
||||||
dirty |= AddCounterChangeNode(*this, aFrame, i++, pair,
|
if (pair.value != 0) {
|
||||||
nsCounterChangeNode::INCREMENT);
|
dirty |= AddCounterChangeNode(*this, aFrame, i++, pair,
|
||||||
|
nsCounterChangeNode::INCREMENT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +361,7 @@ void nsCounterManager::Dump() {
|
|||||||
nsCounterList* list = iter.UserData();
|
nsCounterList* list = iter.UserData();
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
for (nsCounterNode* node = list->First(); node; node = list->Next(node)) {
|
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(
|
printf(
|
||||||
" Node #%d @%p frame=%p index=%d type=%s valAfter=%d\n"
|
" Node #%d @%p frame=%p index=%d type=%s valAfter=%d\n"
|
||||||
" scope-start=%p scope-prev=%p",
|
" scope-start=%p scope-prev=%p",
|
||||||
|
@ -170,6 +170,11 @@ class nsCounterList : public nsGenConList {
|
|||||||
public:
|
public:
|
||||||
nsCounterList() : nsGenConList(), mDirty(false) {}
|
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) {
|
void Insert(nsCounterNode* aNode) {
|
||||||
nsGenConList::Insert(aNode);
|
nsGenConList::Insert(aNode);
|
||||||
// Don't SetScope if we're dirty -- we'll reset all the scopes anyway,
|
// Don't SetScope if we're dirty -- we'll reset all the scopes anyway,
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIContentViewer.h"
|
#include "nsIContentViewer.h"
|
||||||
#include "nsIDocumentViewerPrint.h"
|
#include "nsIDocumentViewerPrint.h"
|
||||||
|
#include "nsIScreen.h"
|
||||||
#include "mozilla/dom/BeforeUnloadEvent.h"
|
#include "mozilla/dom/BeforeUnloadEvent.h"
|
||||||
#include "mozilla/dom/PopupBlocker.h"
|
#include "mozilla/dom/PopupBlocker.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
@ -142,9 +143,6 @@ static mozilla::LazyLogModule gPrintingLog("printing");
|
|||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|
||||||
class nsDocumentViewer;
|
class nsDocumentViewer;
|
||||||
namespace mozilla {
|
|
||||||
class AutoPrintEventDispatcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a small delegate class used to avoid circular references
|
// a small delegate class used to avoid circular references
|
||||||
|
|
||||||
@ -462,7 +460,6 @@ class nsDocumentViewer final : public nsIContentViewer,
|
|||||||
RefPtr<nsPrintJob> mPrintJob;
|
RefPtr<nsPrintJob> mPrintJob;
|
||||||
float mOriginalPrintPreviewScale;
|
float mOriginalPrintPreviewScale;
|
||||||
float mPrintPreviewZoom;
|
float mPrintPreviewZoom;
|
||||||
UniquePtr<AutoPrintEventDispatcher> mAutoBeforeAndAfterPrint;
|
|
||||||
# endif // NS_PRINT_PREVIEW
|
# endif // NS_PRINT_PREVIEW
|
||||||
|
|
||||||
#endif // NS_PRINTING
|
#endif // NS_PRINTING
|
||||||
@ -470,59 +467,12 @@ class nsDocumentViewer final : public nsIContentViewer,
|
|||||||
/* character set member data */
|
/* character set member data */
|
||||||
int32_t mHintCharsetSource;
|
int32_t mHintCharsetSource;
|
||||||
const Encoding* mHintCharset;
|
const Encoding* mHintCharset;
|
||||||
const Encoding* mForceCharacterSet;
|
|
||||||
|
|
||||||
bool mIsPageMode;
|
bool mIsPageMode;
|
||||||
bool mInitializedForPrintPreview;
|
bool mInitializedForPrintPreview;
|
||||||
bool mHidden;
|
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 {
|
class nsDocumentShownDispatcher : public Runnable {
|
||||||
public:
|
public:
|
||||||
explicit nsDocumentShownDispatcher(nsCOMPtr<Document> aDocument)
|
explicit nsDocumentShownDispatcher(nsCOMPtr<Document> aDocument)
|
||||||
@ -593,7 +543,6 @@ nsDocumentViewer::nsDocumentViewer()
|
|||||||
#endif // NS_PRINTING
|
#endif // NS_PRINTING
|
||||||
mHintCharsetSource(kCharsetUninitialized),
|
mHintCharsetSource(kCharsetUninitialized),
|
||||||
mHintCharset(nullptr),
|
mHintCharset(nullptr),
|
||||||
mForceCharacterSet(nullptr),
|
|
||||||
mIsPageMode(false),
|
mIsPageMode(false),
|
||||||
mInitializedForPrintPreview(false),
|
mInitializedForPrintPreview(false),
|
||||||
mHidden(false) {
|
mHidden(false) {
|
||||||
@ -668,10 +617,8 @@ void nsDocumentViewer::RemoveFocusListener() {
|
|||||||
std::move(mFocusListener)) {
|
std::move(mFocusListener)) {
|
||||||
oldListener->Disconnect();
|
oldListener->Disconnect();
|
||||||
if (mDocument) {
|
if (mDocument) {
|
||||||
mDocument->RemoveEventListener(NS_LITERAL_STRING("focus"), oldListener,
|
mDocument->RemoveEventListener(u"focus"_ns, oldListener, false);
|
||||||
false);
|
mDocument->RemoveEventListener(u"blur"_ns, oldListener, false);
|
||||||
mDocument->RemoveEventListener(NS_LITERAL_STRING("blur"), oldListener,
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -680,10 +627,8 @@ void nsDocumentViewer::ReinitializeFocusListener() {
|
|||||||
RemoveFocusListener();
|
RemoveFocusListener();
|
||||||
mFocusListener = new nsDocViewerFocusListener(this);
|
mFocusListener = new nsDocViewerFocusListener(this);
|
||||||
if (mDocument) {
|
if (mDocument) {
|
||||||
mDocument->AddEventListener(NS_LITERAL_STRING("focus"), mFocusListener,
|
mDocument->AddEventListener(u"focus"_ns, mFocusListener, false, false);
|
||||||
false, false);
|
mDocument->AddEventListener(u"blur"_ns, mFocusListener, false, false);
|
||||||
mDocument->AddEventListener(NS_LITERAL_STRING("blur"), mFocusListener,
|
|
||||||
false, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1268,7 +1213,7 @@ nsresult nsDocumentViewer::PermitUnloadInternal(uint32_t* aPermitUnloadFlags,
|
|||||||
nsPresContext* presContext = mDocument->GetPresContext();
|
nsPresContext* presContext = mDocument->GetPresContext();
|
||||||
RefPtr<BeforeUnloadEvent> event =
|
RefPtr<BeforeUnloadEvent> event =
|
||||||
new BeforeUnloadEvent(mDocument, presContext, nullptr);
|
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.
|
// Dispatching to |window|, but using |document| as the target.
|
||||||
event->SetTarget(mDocument);
|
event->SetTarget(mDocument);
|
||||||
@ -1621,14 +1566,6 @@ nsDocumentViewer::Close(nsISHEntry* aSHEntry) {
|
|||||||
mDocument->AddMutationObserver(mBFCachePreventionObserver);
|
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
|
#ifdef NS_PRINTING
|
||||||
// A Close was called while we were printing
|
// A Close was called while we were printing
|
||||||
// so don't clear the ScriptGlobalObject
|
// so don't clear the ScriptGlobalObject
|
||||||
@ -1698,8 +1635,6 @@ nsDocumentViewer::Destroy() {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Dispatch the 'afterprint' event now, if pending:
|
|
||||||
mAutoBeforeAndAfterPrint = nullptr;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We want to make sure to disconnect mBFCachePreventionObserver before we
|
// 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.
|
// Dispatch TextZoomChange event only if text zoom value has changed.
|
||||||
if (textZoomChange) {
|
if (textZoomChange) {
|
||||||
nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
|
nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
|
||||||
NS_LITERAL_STRING("TextZoomChange"),
|
u"TextZoomChange"_ns, CanBubble::eYes,
|
||||||
CanBubble::eYes, Cancelable::eYes);
|
Cancelable::eYes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2717,14 +2652,6 @@ nsDocumentViewer::GetTextZoom(float* aTextZoom) {
|
|||||||
return NS_OK;
|
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
|
NS_IMETHODIMP
|
||||||
nsDocumentViewer::SetFullZoom(float aFullZoom) {
|
nsDocumentViewer::SetFullZoom(float aFullZoom) {
|
||||||
#ifdef NS_PRINT_PREVIEW
|
#ifdef NS_PRINT_PREVIEW
|
||||||
@ -2735,7 +2662,7 @@ nsDocumentViewer::SetFullZoom(float aFullZoom) {
|
|||||||
NS_ENSURE_TRUE(presShell, NS_OK);
|
NS_ENSURE_TRUE(presShell, NS_OK);
|
||||||
|
|
||||||
if (!mPrintPreviewZoomed) {
|
if (!mPrintPreviewZoomed) {
|
||||||
mOriginalPrintPreviewScale = pc->GetPrintPreviewScale();
|
mOriginalPrintPreviewScale = pc->GetPrintPreviewScaleForSequenceFrame();
|
||||||
mPrintPreviewZoomed = true;
|
mPrintPreviewZoomed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2774,8 +2701,8 @@ nsDocumentViewer::SetFullZoom(float aFullZoom) {
|
|||||||
// Dispatch FullZoomChange event only if fullzoom value really has changed.
|
// Dispatch FullZoomChange event only if fullzoom value really has changed.
|
||||||
if (fullZoomChange) {
|
if (fullZoomChange) {
|
||||||
nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
|
nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
|
||||||
NS_LITERAL_STRING("FullZoomChange"),
|
u"FullZoomChange"_ns, CanBubble::eYes,
|
||||||
CanBubble::eYes, Cancelable::eYes);
|
Cancelable::eYes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2798,18 +2725,8 @@ nsDocumentViewer::GetFullZoom(float* aFullZoom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDocumentViewer::GetDeviceFullZoom(float* aDeviceFullZoom) {
|
nsDocumentViewer::GetDeviceFullZoomForTest(float* aDeviceFullZoom) {
|
||||||
NS_ENSURE_ARG_POINTER(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();
|
nsPresContext* pc = GetPresContext();
|
||||||
*aDeviceFullZoom = pc ? pc->GetDeviceFullZoom() : mPageZoom;
|
*aDeviceFullZoom = pc ? pc->GetDeviceFullZoom() : mPageZoom;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2891,46 +2808,6 @@ nsDocumentViewer::StopEmulatingMedium() {
|
|||||||
return NS_OK;
|
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(
|
NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSet(
|
||||||
nsACString& aHintCharacterSet) {
|
nsACString& aHintCharacterSet) {
|
||||||
auto encoding = nsDocumentViewer::GetHintCharset();
|
auto encoding = nsDocumentViewer::GetHintCharset();
|
||||||
@ -3279,7 +3156,7 @@ NS_IMETHODIMP nsDocViewerSelectionListener::NotifySelectionChanged(
|
|||||||
// might need another update string for simple selection changes, but that
|
// might need another update string for simple selection changes, but that
|
||||||
// would be expenseive.
|
// would be expenseive.
|
||||||
if (mSelectionWasCollapsed != selectionCollapsed) {
|
if (mSelectionWasCollapsed != selectionCollapsed) {
|
||||||
domWindow->UpdateCommands(NS_LITERAL_STRING("select"), selection, aReason);
|
domWindow->UpdateCommands(u"select"_ns, selection, aReason);
|
||||||
mSelectionWasCollapsed = selectionCollapsed;
|
mSelectionWasCollapsed = selectionCollapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3379,41 +3256,20 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
|
|||||||
return NS_ERROR_FAILURE;
|
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
|
// If we are hosting a full-page plugin, tell it to print
|
||||||
// first. It shows its own native print UI.
|
// first. It shows its own native print UI.
|
||||||
nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(mDocument));
|
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
|
// Our call to nsPrintJob::Print() may cause mPrintJob to be
|
||||||
// Release()'d in Destroy(). Therefore, we need to grab the instance with
|
// 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.
|
// a local variable, so that it won't be deleted during its own method.
|
||||||
RefPtr<nsPrintJob> printJob = mPrintJob;
|
RefPtr<nsPrintJob> printJob = mPrintJob;
|
||||||
if (!printJob) {
|
if (!printJob) {
|
||||||
NS_ENSURE_STATE(mDeviceContext);
|
|
||||||
printJob = new nsPrintJob();
|
printJob = new nsPrintJob();
|
||||||
|
|
||||||
rv = printJob->Initialize(this, mContainer, mDocument,
|
rv = printJob->Initialize(this, mContainer, mDocument,
|
||||||
@ -3425,12 +3281,17 @@ nsDocumentViewer::Print(nsIPrintSettings* aPrintSettings,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
mPrintJob = printJob;
|
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);
|
rv = printJob->Print(mDocument, aPrintSettings, aWebProgressListener);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
OnDonePrinting();
|
OnDonePrinting();
|
||||||
@ -3472,18 +3333,6 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
|
|||||||
nsCOMPtr<Document> doc = window->GetDoc();
|
nsCOMPtr<Document> doc = window->GetDoc();
|
||||||
NS_ENSURE_STATE(doc);
|
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());
|
NS_ENSURE_STATE(!GetIsPrinting());
|
||||||
// beforeprint event may have caused ContentViewer to be shutdown.
|
// beforeprint event may have caused ContentViewer to be shutdown.
|
||||||
NS_ENSURE_STATE(mContainer);
|
NS_ENSURE_STATE(mContainer);
|
||||||
@ -3506,11 +3355,6 @@ nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings,
|
|||||||
}
|
}
|
||||||
mPrintJob = printJob;
|
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);
|
rv = printJob->PrintPreview(doc, aPrintSettings, aWebProgressListener);
|
||||||
mPrintPreviewZoomed = false;
|
mPrintPreviewZoomed = false;
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
@ -3541,14 +3385,13 @@ nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// in PP mPrtPreview->mPrintObject->mSeqFrame is null
|
// in PP mPrtPreview->mPrintObject->mSeqFrame is null
|
||||||
nsIFrame* seqFrame = nullptr;
|
auto [seqFrame, pageCount] = mPrintJob->GetSeqFrameAndCountPages();
|
||||||
int32_t pageCount = 0;
|
if (!seqFrame) {
|
||||||
if (NS_FAILED(mPrintJob->GetSeqFrameAndCountPages(seqFrame, pageCount))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure where we are currently scrolled to
|
// Figure where we are currently scrolled to
|
||||||
nsPoint pt = sf->GetScrollPosition();
|
nsPoint currentScrollPosition = sf->GetScrollPosition();
|
||||||
|
|
||||||
int32_t pageNum = 1;
|
int32_t pageNum = 1;
|
||||||
nsIFrame* fndPageFrame = nullptr;
|
nsIFrame* fndPageFrame = nullptr;
|
||||||
@ -3562,13 +3405,13 @@ nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
|
|||||||
|
|
||||||
// Now, locate the current page we are on and
|
// Now, locate the current page we are on and
|
||||||
// and the page of the page number
|
// and the page of the page number
|
||||||
for (nsIFrame* pageFrame : seqFrame->PrincipalChildList()) {
|
for (nsIFrame* sheetFrame : seqFrame->PrincipalChildList()) {
|
||||||
nsRect pageRect = pageFrame->GetRect();
|
nsRect sheetRect = sheetFrame->GetRect();
|
||||||
if (pageRect.Contains(pageRect.x, pt.y)) {
|
if (sheetRect.Contains(sheetRect.x, currentScrollPosition.y)) {
|
||||||
currentPage = pageFrame;
|
currentPage = sheetFrame;
|
||||||
}
|
}
|
||||||
if (pageNum == aPageNum) {
|
if (pageNum == aPageNum) {
|
||||||
fndPageFrame = pageFrame;
|
fndPageFrame = sheetFrame;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pageNum++;
|
pageNum++;
|
||||||
@ -3599,9 +3442,10 @@ nsDocumentViewer::PrintPreviewScrollToPage(int16_t aType, int32_t aPageNum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fndPageFrame) {
|
if (fndPageFrame) {
|
||||||
nscoord newYPosn = nscoord(mPrintJob->GetPrintPreviewScale() *
|
nscoord newYPosn = nscoord(seqFrame->GetPrintPreviewScale() *
|
||||||
fndPageFrame->GetPosition().y);
|
fndPageFrame->GetPosition().y);
|
||||||
sf->ScrollTo(nsPoint(pt.x, newYPosn), ScrollMode::Instant);
|
sf->ScrollTo(nsPoint(currentScrollPosition.x, newYPosn),
|
||||||
|
ScrollMode::Instant);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -3687,7 +3531,6 @@ nsDocumentViewer::ExitPrintPreview() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ifdef NS_PRINT_PREVIEW
|
# ifdef NS_PRINT_PREVIEW
|
||||||
mPrintJob->TurnScriptingOn(true);
|
|
||||||
mPrintJob->Destroy();
|
mPrintJob->Destroy();
|
||||||
mPrintJob = nullptr;
|
mPrintJob = nullptr;
|
||||||
|
|
||||||
@ -3718,24 +3561,6 @@ nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) {
|
|||||||
return *aPrintPreviewNumPages > 0 ? NS_OK : NS_ERROR_FAILURE;
|
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
|
// Printing/Print Preview Helpers
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -3814,7 +3639,7 @@ bool nsDocumentViewer::ShouldAttachToTopLevel() {
|
|||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// XXX this always returns false for subdocuments
|
// XXX this always returns false for subdocuments
|
||||||
bool nsDocumentViewer::GetIsPrinting() {
|
bool nsDocumentViewer::GetIsPrinting() const {
|
||||||
#ifdef NS_PRINTING
|
#ifdef NS_PRINTING
|
||||||
if (mPrintJob) {
|
if (mPrintJob) {
|
||||||
return mPrintJob->GetIsPrinting();
|
return mPrintJob->GetIsPrinting();
|
||||||
@ -3835,11 +3660,6 @@ void nsDocumentViewer::SetIsPrinting(bool aIsPrinting) {
|
|||||||
} else {
|
} else {
|
||||||
NS_WARNING("Did you close a window before printing?");
|
NS_WARNING("Did you close a window before printing?");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aIsPrinting) {
|
|
||||||
// Dispatch the 'afterprint' event now, if pending:
|
|
||||||
mAutoBeforeAndAfterPrint = nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3847,7 +3667,7 @@ void nsDocumentViewer::SetIsPrinting(bool aIsPrinting) {
|
|||||||
// The PrintJob holds the current value
|
// The PrintJob holds the current value
|
||||||
// this called from inside the DocViewer.
|
// this called from inside the DocViewer.
|
||||||
// XXX it always returns false for subdocuments
|
// XXX it always returns false for subdocuments
|
||||||
bool nsDocumentViewer::GetIsPrintPreview() {
|
bool nsDocumentViewer::GetIsPrintPreview() const {
|
||||||
#ifdef NS_PRINTING
|
#ifdef NS_PRINTING
|
||||||
if (mPrintJob) {
|
if (mPrintJob) {
|
||||||
return mPrintJob->GetIsPrintPreview();
|
return mPrintJob->GetIsPrintPreview();
|
||||||
@ -3866,10 +3686,6 @@ void nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview) {
|
|||||||
if (docShell || !aIsPrintPreview) {
|
if (docShell || !aIsPrintPreview) {
|
||||||
SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true);
|
SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true);
|
||||||
}
|
}
|
||||||
if (!aIsPrintPreview) {
|
|
||||||
// Dispatch the 'afterprint' event now, if pending:
|
|
||||||
mAutoBeforeAndAfterPrint = nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Protect against pres shell destruction running scripts.
|
// Protect against pres shell destruction running scripts.
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
#define nsGenConList_h___
|
#define nsGenConList_h___
|
||||||
|
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
#include "nsIFrame.h"
|
|
||||||
#include "nsStyleStruct.h"
|
#include "nsStyleStruct.h"
|
||||||
#include "nsCSSPseudoElements.h"
|
#include "nsCSSPseudoElements.h"
|
||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
|
|
||||||
class nsGenConList;
|
class nsGenConList;
|
||||||
|
class nsIFrame;
|
||||||
|
|
||||||
struct nsGenConNode : public mozilla::LinkedListElement<nsGenConNode> {
|
struct nsGenConNode : public mozilla::LinkedListElement<nsGenConNode> {
|
||||||
using StyleContentType = mozilla::StyleContentItem::Tag;
|
using StyleContentType = mozilla::StyleContentItem::Tag;
|
||||||
@ -110,6 +110,11 @@ class nsGenConList {
|
|||||||
// have been destroyed; otherwise false.
|
// have been destroyed; otherwise false.
|
||||||
bool DestroyNodesFor(nsIFrame* aFrame);
|
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|.
|
// Return true if |aNode1| is after |aNode2|.
|
||||||
static bool NodeAfter(const nsGenConNode* aNode1, const nsGenConNode* 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)
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_VIEWER_PRINT_IID)
|
||||||
|
|
||||||
virtual void SetIsPrinting(bool aIsPrinting) = 0;
|
virtual void SetIsPrinting(bool aIsPrinting) = 0;
|
||||||
virtual bool GetIsPrinting() = 0;
|
virtual bool GetIsPrinting() const = 0;
|
||||||
|
|
||||||
virtual void SetIsPrintPreview(bool aIsPrintPreview) = 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()
|
* 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. */
|
/* Use this macro when declaring classes that implement this interface. */
|
||||||
#define NS_DECL_NSIDOCUMENTVIEWERPRINT \
|
#define NS_DECL_NSIDOCUMENTVIEWERPRINT \
|
||||||
void SetIsPrinting(bool aIsPrinting) override; \
|
void SetIsPrinting(bool aIsPrinting) override; \
|
||||||
bool GetIsPrinting() override; \
|
bool GetIsPrinting() const override; \
|
||||||
void SetIsPrintPreview(bool aIsPrintPreview) override; \
|
void SetIsPrintPreview(bool aIsPrintPreview) override; \
|
||||||
bool GetIsPrintPreview() override; \
|
bool GetIsPrintPreview() const override; \
|
||||||
void IncrementDestroyBlockedCount() override; \
|
void IncrementDestroyBlockedCount() override; \
|
||||||
void DecrementDestroyBlockedCount() override; \
|
void DecrementDestroyBlockedCount() override; \
|
||||||
void OnDonePrinting() override; \
|
void OnDonePrinting() override; \
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#define NSIFRAMETRAVERSAL_H
|
#define NSIFRAMETRAVERSAL_H
|
||||||
|
|
||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
#include "nsIFrame.h"
|
|
||||||
|
class nsIFrame;
|
||||||
|
|
||||||
#define NS_IFRAMEENUMERATOR_IID \
|
#define NS_IFRAMEENUMERATOR_IID \
|
||||||
{ \
|
{ \
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,9 @@
|
|||||||
#include "mozilla/LookAndFeel.h"
|
#include "mozilla/LookAndFeel.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/ReflowOutput.h"
|
#include "mozilla/ReflowOutput.h"
|
||||||
|
#include "mozilla/RelativeTo.h"
|
||||||
#include "mozilla/StaticPrefs_nglayout.h"
|
#include "mozilla/StaticPrefs_nglayout.h"
|
||||||
|
#include "mozilla/SurfaceFromElementResult.h"
|
||||||
#include "mozilla/SVGImageContext.h"
|
#include "mozilla/SVGImageContext.h"
|
||||||
#include "mozilla/ToString.h"
|
#include "mozilla/ToString.h"
|
||||||
#include "mozilla/TypedEnumBits.h"
|
#include "mozilla/TypedEnumBits.h"
|
||||||
@ -56,11 +58,11 @@ class nsIFrame;
|
|||||||
class nsPIDOMWindowOuter;
|
class nsPIDOMWindowOuter;
|
||||||
class imgIRequest;
|
class imgIRequest;
|
||||||
struct nsStyleFont;
|
struct nsStyleFont;
|
||||||
struct nsOverflowAreas;
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
struct AspectRatio;
|
struct AspectRatio;
|
||||||
class ComputedStyle;
|
class ComputedStyle;
|
||||||
|
class DisplayPortUtils;
|
||||||
class PresShell;
|
class PresShell;
|
||||||
enum class PseudoStyleType : uint8_t;
|
enum class PseudoStyleType : uint8_t;
|
||||||
class EventListenerManager;
|
class EventListenerManager;
|
||||||
@ -71,7 +73,9 @@ class WritingMode;
|
|||||||
class DisplayItemClip;
|
class DisplayItemClip;
|
||||||
class EffectSet;
|
class EffectSet;
|
||||||
struct ActiveScrolledRoot;
|
struct ActiveScrolledRoot;
|
||||||
|
enum class ScrollOrigin : uint8_t;
|
||||||
enum class StyleImageOrientation : uint8_t;
|
enum class StyleImageOrientation : uint8_t;
|
||||||
|
struct OverflowAreas;
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class CanvasRenderingContext2D;
|
class CanvasRenderingContext2D;
|
||||||
class DOMRectList;
|
class DOMRectList;
|
||||||
@ -100,31 +104,6 @@ class Layer;
|
|||||||
} // namespace layers
|
} // namespace layers
|
||||||
} // namespace mozilla
|
} // 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.
|
// Flags to customize the behavior of nsLayoutUtils::DrawString.
|
||||||
enum class DrawStringFlags {
|
enum class DrawStringFlags {
|
||||||
Default = 0x0,
|
Default = 0x0,
|
||||||
@ -132,6 +111,17 @@ enum class DrawStringFlags {
|
|||||||
};
|
};
|
||||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(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
|
* nsLayoutUtils is a namespace class used for various helper
|
||||||
* functions that are useful in multiple places in layout. The goal
|
* functions that are useful in multiple places in layout. The goal
|
||||||
@ -149,6 +139,9 @@ class nsLayoutUtils {
|
|||||||
#endif
|
#endif
|
||||||
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
|
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
|
||||||
typedef mozilla::IntrinsicSize IntrinsicSize;
|
typedef mozilla::IntrinsicSize IntrinsicSize;
|
||||||
|
typedef mozilla::RelativeTo RelativeTo;
|
||||||
|
typedef mozilla::ScrollOrigin ScrollOrigin;
|
||||||
|
typedef mozilla::ViewportType ViewportType;
|
||||||
typedef mozilla::gfx::SourceSurface SourceSurface;
|
typedef mozilla::gfx::SourceSurface SourceSurface;
|
||||||
typedef mozilla::gfx::Color Color;
|
typedef mozilla::gfx::Color Color;
|
||||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||||
@ -208,134 +201,17 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId);
|
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.
|
* Find the ID for a given scrollable frame.
|
||||||
*/
|
*/
|
||||||
static ViewID FindIDForScrollableFrame(nsIScrollableFrame* aScrollable);
|
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
|
* 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.
|
* is being sent to APZ as part of a paint-skip transaction.
|
||||||
@ -586,8 +462,8 @@ class nsLayoutUtils {
|
|||||||
* aFrame == aAncestorFrame.
|
* aFrame == aAncestorFrame.
|
||||||
*/
|
*/
|
||||||
static bool IsProperAncestorFrameCrossDoc(
|
static bool IsProperAncestorFrameCrossDoc(
|
||||||
nsIFrame* aAncestorFrame, nsIFrame* aFrame,
|
const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
|
||||||
nsIFrame* aCommonAncestor = nullptr);
|
const nsIFrame* aCommonAncestor = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor
|
* IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor
|
||||||
@ -631,19 +507,6 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
static ViewID ScrollIdForRootScrollFrame(nsPresContext* aPresContext);
|
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
|
* 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.
|
* @param aDirection Whether it's for horizontal or vertical scrolling.
|
||||||
* @return the nearest scrollable frame or nullptr if not found
|
* @return the nearest scrollable frame or nullptr if not found
|
||||||
*/
|
*/
|
||||||
enum Direction { eHorizontal, eVertical };
|
|
||||||
static nsIScrollableFrame* GetNearestScrollableFrameForDirection(
|
static nsIScrollableFrame* GetNearestScrollableFrameForDirection(
|
||||||
nsIFrame* aFrame, Direction aDirection);
|
nsIFrame* aFrame, ScrollableDirection aDirection);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/**
|
/**
|
||||||
@ -770,7 +632,7 @@ class nsLayoutUtils {
|
|||||||
* the event is not a GUI event).
|
* the event is not a GUI event).
|
||||||
*/
|
*/
|
||||||
static nsPoint GetEventCoordinatesRelativeTo(
|
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
|
* Get the coordinates of a given point relative to an event and a
|
||||||
@ -784,7 +646,7 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
static nsPoint GetEventCoordinatesRelativeTo(
|
static nsPoint GetEventCoordinatesRelativeTo(
|
||||||
const mozilla::WidgetEvent* aEvent,
|
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
|
* Get the coordinates of a given point relative to a widget and a
|
||||||
@ -798,7 +660,7 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
static nsPoint GetEventCoordinatesRelativeTo(
|
static nsPoint GetEventCoordinatesRelativeTo(
|
||||||
nsIWidget* aWidget, const mozilla::LayoutDeviceIntPoint& aPoint,
|
nsIWidget* aWidget, const mozilla::LayoutDeviceIntPoint& aPoint,
|
||||||
nsIFrame* aFrame);
|
RelativeTo aFrame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the popup frame of a given native mouse event.
|
* Get the popup frame of a given native mouse event.
|
||||||
@ -844,12 +706,13 @@ class nsLayoutUtils {
|
|||||||
* @param aPresContext the PresContext for the view
|
* @param aPresContext the PresContext for the view
|
||||||
* @param aView the view
|
* @param aView the view
|
||||||
* @param aPt the point relative to 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
|
* @param aWidget the widget to which returned coordinates are relative
|
||||||
* @return the point in the view's coordinates
|
* @return the point in the view's coordinates
|
||||||
*/
|
*/
|
||||||
static mozilla::LayoutDeviceIntPoint TranslateViewToWidget(
|
static mozilla::LayoutDeviceIntPoint TranslateViewToWidget(
|
||||||
nsPresContext* aPresContext, nsView* aView, nsPoint aPt,
|
nsPresContext* aPresContext, nsView* aView, nsPoint aPt,
|
||||||
nsIWidget* aWidget);
|
ViewportType aViewportType, nsIWidget* aWidget);
|
||||||
|
|
||||||
static mozilla::LayoutDeviceIntPoint WidgetToWidgetOffset(
|
static mozilla::LayoutDeviceIntPoint WidgetToWidgetOffset(
|
||||||
nsIWidget* aFromWidget, nsIWidget* aToWidget);
|
nsIWidget* aFromWidget, nsIWidget* aToWidget);
|
||||||
@ -879,21 +742,23 @@ class nsLayoutUtils {
|
|||||||
* Given aFrame, the root frame of a stacking context, find its descendant
|
* 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,
|
* frame under the point aPt that receives a mouse event at that location,
|
||||||
* or nullptr if there is no such frame.
|
* 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.
|
* @param aFlags some combination of FrameForPointOption.
|
||||||
*/
|
*/
|
||||||
static nsIFrame* GetFrameForPoint(const nsIFrame* aFrame, nsPoint aPt,
|
static nsIFrame* GetFrameForPoint(RelativeTo aRelativeTo, nsPoint aPt,
|
||||||
mozilla::EnumSet<FrameForPointOption> = {});
|
mozilla::EnumSet<FrameForPointOption> = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given aFrame, the root frame of a stacking context, find all descendant
|
* Given aFrame, the root frame of a stacking context, find all descendant
|
||||||
* frames under the area of a rectangle that receives a mouse event,
|
* frames under the area of a rectangle that receives a mouse event,
|
||||||
* or nullptr if there is no such frame.
|
* 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 aOutFrames an array to add all the frames found
|
||||||
* @param aFlags some combination of FrameForPointOption.
|
* @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,
|
nsTArray<nsIFrame*>& aOutFrames,
|
||||||
mozilla::EnumSet<FrameForPointOption> = {});
|
mozilla::EnumSet<FrameForPointOption> = {});
|
||||||
|
|
||||||
@ -902,6 +767,8 @@ class nsLayoutUtils {
|
|||||||
* aAncestor. Computes the bounding-box of the true quadrilateral.
|
* aAncestor. Computes the bounding-box of the true quadrilateral.
|
||||||
* Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if
|
* Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if
|
||||||
* we only need to use a 2d transform that PreservesAxisAlignedRectangles().
|
* 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
|
* |aMatrixCache| allows for optimizations in recomputing the same matrix over
|
||||||
* and over. The argument can be one of the following values:
|
* and over. The argument can be one of the following values:
|
||||||
@ -922,6 +789,17 @@ class nsLayoutUtils {
|
|||||||
bool* aPreservesAxisAlignedRectangles = nullptr,
|
bool* aPreservesAxisAlignedRectangles = nullptr,
|
||||||
mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
|
mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
|
||||||
bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false,
|
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);
|
nsIFrame** aOutAncestor = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -930,9 +808,41 @@ class nsLayoutUtils {
|
|||||||
* flag in aFlags will return CSS pixels, by default it returns device
|
* flag in aFlags will return CSS pixels, by default it returns device
|
||||||
* pixels.
|
* pixels.
|
||||||
* More info can be found in nsIFrame::GetTransformMatrix.
|
* 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(
|
static Matrix4x4Flagged GetTransformToAncestor(
|
||||||
const nsIFrame* aFrame, const nsIFrame* aAncestor, uint32_t aFlags = 0,
|
RelativeTo aFrame, RelativeTo aAncestor, uint32_t aFlags = 0,
|
||||||
nsIFrame** aOutAncestor = nullptr);
|
nsIFrame** aOutAncestor = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -953,8 +863,17 @@ class nsLayoutUtils {
|
|||||||
* Find the nearest common ancestor frame for aFrame1 and aFrame2. The
|
* Find the nearest common ancestor frame for aFrame1 and aFrame2. The
|
||||||
* ancestor frame could be cross-doc.
|
* ancestor frame could be cross-doc.
|
||||||
*/
|
*/
|
||||||
static nsIFrame* FindNearestCommonAncestorFrame(nsIFrame* aFrame1,
|
static const nsIFrame* FindNearestCommonAncestorFrame(
|
||||||
nsIFrame* aFrame2);
|
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
|
* 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
|
* Same as above function, but transform points in app units and
|
||||||
* handle 1 point per call.
|
* handle 1 point per call.
|
||||||
*/
|
*/
|
||||||
static TransformResult TransformPoint(nsIFrame* aFromFrame,
|
static TransformResult TransformPoint(RelativeTo aFromFrame,
|
||||||
nsIFrame* aToFrame, nsPoint& aPoint);
|
RelativeTo aToFrame, nsPoint& aPoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms a rect from aFromFrame to aToFrame. In app units.
|
* Transforms a rect from aFromFrame to aToFrame. In app units.
|
||||||
* Returns the bounds of the actual rect if the transform requires rotation
|
* Returns the bounds of the actual rect if the transform requires rotation
|
||||||
* or anything complex like that.
|
* or anything complex like that.
|
||||||
*/
|
*/
|
||||||
static TransformResult TransformRect(nsIFrame* aFromFrame, nsIFrame* aToFrame,
|
static TransformResult TransformRect(const nsIFrame* aFromFrame,
|
||||||
nsRect& aRect);
|
const nsIFrame* aToFrame, nsRect& aRect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts app units to pixels (with optional snapping) and appends as a
|
* 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
|
* in the coordinate system of aFrame. This effectively inverts all
|
||||||
* transforms between this point and the root frame.
|
* 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 aFrame The frame that acts as the coordinate space container.
|
||||||
* @param aPoint The point, in the global space, to get in the frame-local
|
* @param aPoint The point, in global layout or visual coordinates (as per
|
||||||
* space.
|
* |aFromType|, to get in the frame-local space.
|
||||||
* @return aPoint, expressed in aFrame's canonical coordinate 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) {
|
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
|
* Transform aPoint relative to aAncestor down to the coordinate system of
|
||||||
* aFrame.
|
* aFrame.
|
||||||
*/
|
*/
|
||||||
static nsPoint TransformAncestorPointToFrame(nsIFrame* aFrame,
|
static nsPoint TransformAncestorPointToFrame(RelativeTo aFrame,
|
||||||
const nsPoint& aPoint,
|
const nsPoint& aPoint,
|
||||||
nsIFrame* aAncestor);
|
RelativeTo aAncestor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that, given a rectangle and a matrix, returns the smallest
|
* Helper function that, given a rectangle and a matrix, returns the smallest
|
||||||
@ -1116,9 +1039,6 @@ class nsLayoutUtils {
|
|||||||
const nscoord aRadii[8],
|
const nscoord aRadii[8],
|
||||||
const nsRect& aTestRect);
|
const nsRect& aTestRect);
|
||||||
|
|
||||||
static bool MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
|
||||||
nsIFrame* aFrame, nsDisplayListBuilder* aBuilder);
|
|
||||||
|
|
||||||
enum class PaintFrameFlags : uint32_t {
|
enum class PaintFrameFlags : uint32_t {
|
||||||
InTransform = 0x01,
|
InTransform = 0x01,
|
||||||
SyncDecodeImages = 0x02,
|
SyncDecodeImages = 0x02,
|
||||||
@ -1234,12 +1154,7 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame);
|
static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame);
|
||||||
|
|
||||||
class RectCallback {
|
struct RectAccumulator : public mozilla::RectCallback {
|
||||||
public:
|
|
||||||
virtual void AddRect(const nsRect& aRect) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RectAccumulator : public RectCallback {
|
|
||||||
nsRect mResultRect;
|
nsRect mResultRect;
|
||||||
nsRect mFirstRect;
|
nsRect mFirstRect;
|
||||||
bool mSeenFirstRect;
|
bool mSeenFirstRect;
|
||||||
@ -1249,7 +1164,7 @@ class nsLayoutUtils {
|
|||||||
virtual void AddRect(const nsRect& aRect) override;
|
virtual void AddRect(const nsRect& aRect) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RectListBuilder : public RectCallback {
|
struct RectListBuilder : public mozilla::RectCallback {
|
||||||
DOMRectList* mRectList;
|
DOMRectList* mRectList;
|
||||||
|
|
||||||
explicit RectListBuilder(DOMRectList* aList);
|
explicit RectListBuilder(DOMRectList* aList);
|
||||||
@ -1283,10 +1198,12 @@ class nsLayoutUtils {
|
|||||||
* Otherwise (by default), the border box is used.
|
* Otherwise (by default), the border box is used.
|
||||||
*/
|
*/
|
||||||
static void GetAllInFlowRects(nsIFrame* aFrame, const nsIFrame* aRelativeTo,
|
static void GetAllInFlowRects(nsIFrame* aFrame, const nsIFrame* aRelativeTo,
|
||||||
RectCallback* aCallback, uint32_t aFlags = 0);
|
mozilla::RectCallback* aCallback,
|
||||||
|
uint32_t aFlags = 0);
|
||||||
|
|
||||||
static void GetAllInFlowRectsAndTexts(
|
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);
|
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:
|
* size by reducing the *content size* (flooring at zero). This is used for:
|
||||||
* https://drafts.csswg.org/css-grid/#min-size-auto
|
* 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 {
|
enum {
|
||||||
IGNORE_PADDING = 0x01,
|
IGNORE_PADDING = 0x01,
|
||||||
BAIL_IF_REFLOW_NEEDED = 0x02, // returns NS_INTRINSIC_ISIZE_UNKNOWN if so
|
BAIL_IF_REFLOW_NEEDED = 0x02, // returns NS_INTRINSIC_ISIZE_UNKNOWN if so
|
||||||
@ -1488,7 +1402,7 @@ class nsLayoutUtils {
|
|||||||
};
|
};
|
||||||
static nscoord IntrinsicForAxis(
|
static nscoord IntrinsicForAxis(
|
||||||
mozilla::PhysicalAxis aAxis, gfxContext* aRenderingContext,
|
mozilla::PhysicalAxis aAxis, gfxContext* aRenderingContext,
|
||||||
nsIFrame* aFrame, IntrinsicISizeType aType,
|
nsIFrame* aFrame, mozilla::IntrinsicISizeType aType,
|
||||||
const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(),
|
const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(),
|
||||||
uint32_t aFlags = 0, nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE);
|
uint32_t aFlags = 0, nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE);
|
||||||
/**
|
/**
|
||||||
@ -1496,7 +1410,7 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
static nscoord IntrinsicForContainer(gfxContext* aRenderingContext,
|
static nscoord IntrinsicForContainer(gfxContext* aRenderingContext,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
IntrinsicISizeType aType,
|
mozilla::IntrinsicISizeType aType,
|
||||||
uint32_t aFlags = 0);
|
uint32_t aFlags = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1520,7 +1434,7 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
static nscoord MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis,
|
static nscoord MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis,
|
||||||
gfxContext* aRC, nsIFrame* aFrame,
|
gfxContext* aRC, nsIFrame* aFrame,
|
||||||
IntrinsicISizeType aType,
|
mozilla::IntrinsicISizeType aType,
|
||||||
const LogicalSize& aPercentageBasis,
|
const LogicalSize& aPercentageBasis,
|
||||||
uint32_t aFlags = 0);
|
uint32_t aFlags = 0);
|
||||||
|
|
||||||
@ -2150,87 +2064,21 @@ class nsLayoutUtils {
|
|||||||
SFE_USE_ELEMENT_SIZE_IF_VECTOR = 1 << 5
|
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.
|
// This function can be called on any thread.
|
||||||
static SurfaceFromElementResult SurfaceFromOffscreenCanvas(
|
static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas(
|
||||||
mozilla::dom::OffscreenCanvas* aOffscreenCanvas, uint32_t aSurfaceFlags,
|
mozilla::dom::OffscreenCanvas* aOffscreenCanvas, uint32_t aSurfaceFlags,
|
||||||
RefPtr<DrawTarget>& aTarget);
|
RefPtr<DrawTarget>& aTarget);
|
||||||
static SurfaceFromElementResult SurfaceFromOffscreenCanvas(
|
static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas(
|
||||||
mozilla::dom::OffscreenCanvas* aOffscreenCanvas,
|
mozilla::dom::OffscreenCanvas* aOffscreenCanvas,
|
||||||
uint32_t aSurfaceFlags = 0) {
|
uint32_t aSurfaceFlags = 0) {
|
||||||
RefPtr<DrawTarget> target = nullptr;
|
RefPtr<DrawTarget> target = nullptr;
|
||||||
return SurfaceFromOffscreenCanvas(aOffscreenCanvas, aSurfaceFlags, target);
|
return SurfaceFromOffscreenCanvas(aOffscreenCanvas, aSurfaceFlags, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SurfaceFromElementResult SurfaceFromElement(
|
static mozilla::SurfaceFromElementResult SurfaceFromElement(
|
||||||
mozilla::dom::Element* aElement, uint32_t aSurfaceFlags,
|
mozilla::dom::Element* aElement, uint32_t aSurfaceFlags,
|
||||||
RefPtr<DrawTarget>& aTarget);
|
RefPtr<DrawTarget>& aTarget);
|
||||||
static SurfaceFromElementResult SurfaceFromElement(
|
static mozilla::SurfaceFromElementResult SurfaceFromElement(
|
||||||
mozilla::dom::Element* aElement, uint32_t aSurfaceFlags = 0) {
|
mozilla::dom::Element* aElement, uint32_t aSurfaceFlags = 0) {
|
||||||
RefPtr<DrawTarget> target = nullptr;
|
RefPtr<DrawTarget> target = nullptr;
|
||||||
return SurfaceFromElement(aElement, aSurfaceFlags, target);
|
return SurfaceFromElement(aElement, aSurfaceFlags, target);
|
||||||
@ -2238,19 +2086,19 @@ class nsLayoutUtils {
|
|||||||
|
|
||||||
// There are a bunch of callers of SurfaceFromElement. Just mark it as
|
// There are a bunch of callers of SurfaceFromElement. Just mark it as
|
||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
static SurfaceFromElementResult SurfaceFromElement(
|
static mozilla::SurfaceFromElementResult SurfaceFromElement(
|
||||||
nsIImageLoadingContent* aElement, uint32_t aSurfaceFlags,
|
nsIImageLoadingContent* aElement, uint32_t aSurfaceFlags,
|
||||||
RefPtr<DrawTarget>& aTarget);
|
RefPtr<DrawTarget>& aTarget);
|
||||||
// Need an HTMLImageElement overload, because otherwise the
|
// Need an HTMLImageElement overload, because otherwise the
|
||||||
// nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous
|
// nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous
|
||||||
// for HTMLImageElement.
|
// for HTMLImageElement.
|
||||||
static SurfaceFromElementResult SurfaceFromElement(
|
static mozilla::SurfaceFromElementResult SurfaceFromElement(
|
||||||
mozilla::dom::HTMLImageElement* aElement, uint32_t aSurfaceFlags,
|
mozilla::dom::HTMLImageElement* aElement, uint32_t aSurfaceFlags,
|
||||||
RefPtr<DrawTarget>& aTarget);
|
RefPtr<DrawTarget>& aTarget);
|
||||||
static SurfaceFromElementResult SurfaceFromElement(
|
static mozilla::SurfaceFromElementResult SurfaceFromElement(
|
||||||
mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags,
|
mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags,
|
||||||
RefPtr<DrawTarget>& aTarget);
|
RefPtr<DrawTarget>& aTarget);
|
||||||
static SurfaceFromElementResult SurfaceFromElement(
|
static mozilla::SurfaceFromElementResult SurfaceFromElement(
|
||||||
mozilla::dom::HTMLVideoElement* aElement, uint32_t aSurfaceFlags,
|
mozilla::dom::HTMLVideoElement* aElement, uint32_t aSurfaceFlags,
|
||||||
RefPtr<DrawTarget>& aTarget);
|
RefPtr<DrawTarget>& aTarget);
|
||||||
|
|
||||||
@ -2443,7 +2291,7 @@ class nsLayoutUtils {
|
|||||||
* kSelectPopupList and kPopupList are always skipped.
|
* kSelectPopupList and kPopupList are always skipped.
|
||||||
*/
|
*/
|
||||||
static void UnionChildOverflow(
|
static void UnionChildOverflow(
|
||||||
nsIFrame* aFrame, nsOverflowAreas& aOverflowAreas,
|
nsIFrame* aFrame, mozilla::OverflowAreas& aOverflowAreas,
|
||||||
mozilla::layout::FrameChildListIDs aSkipChildLists =
|
mozilla::layout::FrameChildListIDs aSkipChildLists =
|
||||||
mozilla::layout::FrameChildListIDs());
|
mozilla::layout::FrameChildListIDs());
|
||||||
|
|
||||||
@ -2624,12 +2472,12 @@ class nsLayoutUtils {
|
|||||||
*/
|
*/
|
||||||
enum class SubtractDynamicToolbar { No, Yes };
|
enum class SubtractDynamicToolbar { No, Yes };
|
||||||
static bool GetContentViewerSize(
|
static bool GetContentViewerSize(
|
||||||
nsPresContext* aPresContext, LayoutDeviceIntSize& aOutSize,
|
const nsPresContext* aPresContext, LayoutDeviceIntSize& aOutSize,
|
||||||
SubtractDynamicToolbar = SubtractDynamicToolbar::Yes);
|
SubtractDynamicToolbar = SubtractDynamicToolbar::Yes);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool UpdateCompositionBoundsForRCDRSF(
|
static bool UpdateCompositionBoundsForRCDRSF(
|
||||||
mozilla::ParentLayerRect& aCompBounds, nsPresContext* aPresContext);
|
mozilla::ParentLayerRect& aCompBounds, const nsPresContext* aPresContext);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -2657,7 +2505,7 @@ class nsLayoutUtils {
|
|||||||
* mDevPixelsPerCSSPixel set.
|
* mDevPixelsPerCSSPixel set.
|
||||||
*/
|
*/
|
||||||
static CSSSize CalculateRootCompositionSize(
|
static CSSSize CalculateRootCompositionSize(
|
||||||
nsIFrame* aFrame, bool aIsRootContentDocRootScrollFrame,
|
const nsIFrame* aFrame, bool aIsRootContentDocRootScrollFrame,
|
||||||
const FrameMetrics& aMetrics);
|
const FrameMetrics& aMetrics);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2667,7 +2515,7 @@ class nsLayoutUtils {
|
|||||||
* scrollable rect as the rect of the root frame.
|
* scrollable rect as the rect of the root frame.
|
||||||
*/
|
*/
|
||||||
static nsRect CalculateScrollableRectForFrame(
|
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
|
* Calculate the expanded scrollable rect for a frame. See FrameMetrics.h for
|
||||||
@ -2764,47 +2612,8 @@ class nsLayoutUtils {
|
|||||||
static FrameMetrics CalculateBasicFrameMetrics(
|
static FrameMetrics CalculateBasicFrameMetrics(
|
||||||
nsIScrollableFrame* aScrollFrame);
|
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);
|
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(
|
static void SetBSizeFromFontMetrics(
|
||||||
const nsIFrame* aFrame, mozilla::ReflowOutput& aMetrics,
|
const nsIFrame* aFrame, mozilla::ReflowOutput& aMetrics,
|
||||||
const mozilla::LogicalMargin& aFramePadding, mozilla::WritingMode aLineWM,
|
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
|
* returns true for those, and returns false for other origins like APZ
|
||||||
* itself, or scroll position updates from the history restore code.
|
* itself, or scroll position updates from the history restore code.
|
||||||
*/
|
*/
|
||||||
static bool CanScrollOriginClobberApz(nsAtom* aScrollOrigin);
|
static bool CanScrollOriginClobberApz(ScrollOrigin aScrollOrigin);
|
||||||
|
|
||||||
static ScrollMetadata ComputeScrollMetadata(
|
static ScrollMetadata ComputeScrollMetadata(
|
||||||
nsIFrame* aForFrame, nsIFrame* aScrollFrame, nsIContent* aContent,
|
nsIFrame* aForFrame, nsIFrame* aScrollFrame,
|
||||||
const nsIFrame* aReferenceFrame,
|
nsIContent* aContent, const nsIFrame* aReferenceFrame,
|
||||||
mozilla::layers::LayerManager* aLayerManager, ViewID aScrollParentId,
|
mozilla::layers::LayerManager* aLayerManager, ViewID aScrollParentId,
|
||||||
const nsRect& aViewport, const mozilla::Maybe<nsRect>& aClipRect,
|
const nsSize& aScrollPortSize, const mozilla::Maybe<nsRect>& aClipRect,
|
||||||
bool aIsRoot,
|
bool aIsRoot,
|
||||||
const mozilla::Maybe<ContainerLayerParameters>& aContainerParameters);
|
const mozilla::Maybe<ContainerLayerParameters>& aContainerParameters);
|
||||||
|
|
||||||
@ -2859,7 +2668,7 @@ class nsLayoutUtils {
|
|||||||
* scrollable content.
|
* scrollable content.
|
||||||
*/
|
*/
|
||||||
static nsMargin ScrollbarAreaToExcludeFromCompositionBoundsFor(
|
static nsMargin ScrollbarAreaToExcludeFromCompositionBoundsFor(
|
||||||
nsIFrame* aScrollFrame);
|
const nsIFrame* aScrollFrame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks in the layer subtree rooted at aLayer for a metrics with scroll id
|
* 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,
|
static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
|
||||||
nsIFrame* aFrame);
|
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
|
// Callers are responsible to ensure the user-font-set is up-to-date if
|
||||||
// aUseUserFontSet is true.
|
// aUseUserFontSet is true.
|
||||||
static already_AddRefed<nsFontMetrics> GetMetricsFor(
|
static already_AddRefed<nsFontMetrics> GetMetricsFor(
|
||||||
|
@ -495,7 +495,7 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) {
|
|||||||
mMissingFonts = nullptr;
|
mMissingFonts = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (StringBeginsWith(prefName, NS_LITERAL_CSTRING("font.")) ||
|
if (StringBeginsWith(prefName, "font."_ns) ||
|
||||||
prefName.EqualsLiteral("intl.accept_languages")) {
|
prefName.EqualsLiteral("intl.accept_languages")) {
|
||||||
// Changes to font family preferences don't change anything in the
|
// Changes to font family preferences don't change anything in the
|
||||||
// computed style data, so the style system won't generate a reflow
|
// 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).
|
// bother (yet, anyway).
|
||||||
mPrefChangePendingNeedsReflow = true;
|
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)
|
// Changes to bidi prefs need to trigger a reflow (see bug 443629)
|
||||||
mPrefChangePendingNeedsReflow = true;
|
mPrefChangePendingNeedsReflow = true;
|
||||||
|
|
||||||
// Changes to bidi.numeral also needs to empty the text run cache.
|
// Changes to bidi.numeral also needs to empty the text run cache.
|
||||||
// This is handled in gfxTextRunWordCache.cpp.
|
// 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
|
// Changes to font_rendering prefs need to trigger a reflow
|
||||||
mPrefChangePendingNeedsReflow = true;
|
mPrefChangePendingNeedsReflow = true;
|
||||||
}
|
}
|
||||||
@ -803,7 +803,7 @@ nsPresContext* nsPresContext::GetParentPresContext() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPresContext* nsPresContext::GetToplevelContentDocumentPresContext() {
|
nsPresContext* nsPresContext::GetInProcessRootContentDocumentPresContext() {
|
||||||
if (IsChrome()) return nullptr;
|
if (IsChrome()) return nullptr;
|
||||||
nsPresContext* pc = this;
|
nsPresContext* pc = this;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -1191,7 +1191,7 @@ void nsPresContext::RecordInteractionTime(InteractionType aType,
|
|||||||
// Record the interaction time if it occurs after the first paint
|
// Record the interaction time if it occurs after the first paint
|
||||||
// of the top level content document.
|
// of the top level content document.
|
||||||
nsPresContext* topContentPresContext =
|
nsPresContext* topContentPresContext =
|
||||||
GetToplevelContentDocumentPresContext();
|
GetInProcessRootContentDocumentPresContext();
|
||||||
|
|
||||||
if (!topContentPresContext) {
|
if (!topContentPresContext) {
|
||||||
// There is no top content pres context so we don't care
|
// 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() {
|
void nsPresContext::ThemeChangedInternal() {
|
||||||
mPendingThemeChanged = false;
|
mPendingThemeChanged = false;
|
||||||
|
|
||||||
@ -1291,8 +1286,11 @@ void nsPresContext::ThemeChangedInternal() {
|
|||||||
// Recursively notify all remote leaf descendants that the
|
// Recursively notify all remote leaf descendants that the
|
||||||
// system theme has changed.
|
// system theme has changed.
|
||||||
if (nsPIDOMWindowOuter* window = mDocument->GetWindow()) {
|
if (nsPIDOMWindowOuter* window = mDocument->GetWindow()) {
|
||||||
nsContentUtils::CallOnAllRemoteChildren(window, NotifyThemeChanged,
|
nsContentUtils::CallOnAllRemoteChildren(
|
||||||
nullptr);
|
window, [](BrowserParent* aBrowserParent) -> bool {
|
||||||
|
aBrowserParent->ThemeChanged();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1506,10 +1504,6 @@ void nsPresContext::FlushPendingMediaFeatureValuesChanged() {
|
|||||||
RebuildAllStyleData(change.mChangeHint, change.mRestyleHint);
|
RebuildAllStyleData(change.mChangeHint, change.mRestyleHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPresShell || !mPresShell->DidInitialize()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDocument->IsBeingUsedAsImage()) {
|
if (mDocument->IsBeingUsedAsImage()) {
|
||||||
MOZ_ASSERT(mDocument->MediaQueryLists().isEmpty());
|
MOZ_ASSERT(mDocument->MediaQueryLists().isEmpty());
|
||||||
return;
|
return;
|
||||||
@ -1517,12 +1511,15 @@ void nsPresContext::FlushPendingMediaFeatureValuesChanged() {
|
|||||||
|
|
||||||
mDocument->NotifyMediaFeatureValuesChanged();
|
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
|
// Media query list listeners should be notified from a queued task
|
||||||
// (in HTML5 terms), although we also want to notify them on certain
|
// (in HTML5 terms), although we also want to notify them on certain
|
||||||
// flushes. (We're already running off an event.)
|
// 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
|
// Note that we do this after the new style from media queries in
|
||||||
// style sheets has been computed.
|
// 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
|
// We build a list of all the notifications we're going to send
|
||||||
// before we send any of them.
|
// before we send any of them.
|
||||||
|
nsTArray<RefPtr<mozilla::dom::MediaQueryList>> listsToNotify;
|
||||||
// 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;
|
|
||||||
for (MediaQueryList* mql = mDocument->MediaQueryLists().getFirst(); mql;
|
for (MediaQueryList* mql = mDocument->MediaQueryLists().getFirst(); mql;
|
||||||
mql = static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext()) {
|
mql = static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext()) {
|
||||||
localMediaQueryLists.AppendElement(mql);
|
if (mql->MediaFeatureValuesChanged()) {
|
||||||
|
listsToNotify.AppendElement(mql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now iterate our local array of the lists.
|
nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
|
||||||
for (const auto& mql : localMediaQueryLists) {
|
"nsPresContext::FlushPendingMediaFeatureValuesChanged",
|
||||||
nsAutoMicroTask mt;
|
[list = std::move(listsToNotify)] {
|
||||||
mql->MaybeNotify();
|
for (const auto& mql : list) {
|
||||||
}
|
nsAutoMicroTask mt;
|
||||||
}
|
mql->FireChangeEvent();
|
||||||
|
}
|
||||||
static bool NotifyTabSizeModeChanged(BrowserParent* aTab, void* aArg) {
|
}));
|
||||||
nsSizeMode* sizeMode = static_cast<nsSizeMode*>(aArg);
|
|
||||||
aTab->SizeModeChanged(*sizeMode);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsPresContext::SizeModeChanged(nsSizeMode aSizeMode) {
|
void nsPresContext::SizeModeChanged(nsSizeMode aSizeMode) {
|
||||||
if (nsPIDOMWindowOuter* window = mDocument->GetWindow()) {
|
if (nsPIDOMWindowOuter* window = mDocument->GetWindow()) {
|
||||||
nsContentUtils::CallOnAllRemoteChildren(window, NotifyTabSizeModeChanged,
|
nsContentUtils::CallOnAllRemoteChildren(
|
||||||
&aSizeMode);
|
window, [&aSizeMode](BrowserParent* aBrowserParent) -> bool {
|
||||||
|
aBrowserParent->SizeModeChanged(aSizeMode);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
MediaFeatureValuesChangedAllDocuments(
|
MediaFeatureValuesChangedAllDocuments(
|
||||||
{MediaFeatureChangeReason::SizeModeChange});
|
{MediaFeatureChangeReason::SizeModeChange});
|
||||||
@ -1573,7 +1569,24 @@ void nsPresContext::SetPaginatedScrolling(bool aPaginated) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nsPresContext::SetPrintSettings(nsIPrintSettings* aPrintSettings) {
|
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() {
|
bool nsPresContext::EnsureVisible() {
|
||||||
@ -2442,7 +2455,7 @@ void nsRootPresContext::ComputePluginGeometryUpdates(
|
|||||||
// again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
|
// again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
|
||||||
// again.
|
// again.
|
||||||
aBuilder->SetAllowMergingAndFlattening(false);
|
aBuilder->SetAllowMergingAndFlattening(false);
|
||||||
nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
|
nsRegion region = rootFrame->InkOverflowRectRelativeToSelf();
|
||||||
// nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
|
// nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
|
||||||
// widget configuration for the plugin, if it's visible.
|
// widget configuration for the plugin, if it's visible.
|
||||||
aList->ComputeVisibilityForRoot(aBuilder, ®ion);
|
aList->ComputeVisibilityForRoot(aBuilder, ®ion);
|
||||||
|
@ -179,10 +179,10 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||||||
nsPresContext* GetParentPresContext();
|
nsPresContext* GetParentPresContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the prescontext of the toplevel content document that contains
|
* Returns the prescontext of the root content document in the same process
|
||||||
* this presentation, or null if there isn't one.
|
* 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.
|
* 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
|
* 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; }
|
void SetPageSize(nsSize aSize) { mPageSize = aSize; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -421,14 +422,19 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||||||
void SetPageScale(float aScale) { mPageScale = aScale; }
|
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.
|
* 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
|
* 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
|
* does not affect layout. It only affects the size of the onscreen pages
|
||||||
* in print preview.
|
* 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
|
* XXX Temporary: see http://wiki.mozilla.org/Gecko:PrintPreview
|
||||||
*/
|
*/
|
||||||
float GetPrintPreviewScale() { return mPPScale; }
|
float GetPrintPreviewScaleForSequenceFrame() { return mPPScale; }
|
||||||
void SetPrintPreviewScale(float aScale) { mPPScale = aScale; }
|
void SetPrintPreviewScale(float aScale) { mPPScale = aScale; }
|
||||||
|
|
||||||
nsDeviceContext* DeviceContext() const { return mDeviceContext; }
|
nsDeviceContext* DeviceContext() const { return mDeviceContext; }
|
||||||
@ -1132,6 +1138,16 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||||||
|
|
||||||
nsRect mVisibleArea;
|
nsRect mVisibleArea;
|
||||||
nsSize mPageSize;
|
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 mPageScale;
|
||||||
float mPPScale;
|
float mPPScale;
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "mozilla/AutoRestore.h"
|
#include "mozilla/AutoRestore.h"
|
||||||
#include "mozilla/BasePrincipal.h"
|
#include "mozilla/BasePrincipal.h"
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
|
#include "mozilla/DisplayPortUtils.h"
|
||||||
#include "mozilla/IntegerRange.h"
|
#include "mozilla/IntegerRange.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/dom/FontTableURIProtocolHandler.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
|
// in the queue. This will prevent us from spending precious time
|
||||||
// painting a stale displayport.
|
// painting a stale displayport.
|
||||||
if (StaticPrefs::apz_peek_messages_enabled()) {
|
if (StaticPrefs::apz_peek_messages_enabled()) {
|
||||||
nsLayoutUtils::UpdateDisplayPortMarginsFromPendingMessages();
|
DisplayPortUtils::UpdateDisplayPortMarginsFromPendingMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoTArray<nsCOMPtr<nsIRunnable>, 16> earlyRunners = std::move(mEarlyRunners);
|
AutoTArray<nsCOMPtr<nsIRunnable>, 16> earlyRunners = std::move(mEarlyRunners);
|
||||||
|
@ -20,16 +20,15 @@
|
|||||||
#include "nsTHashtable.h"
|
#include "nsTHashtable.h"
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
|
#include "nsRefreshObservers.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/dom/VisualViewport.h"
|
#include "mozilla/dom/VisualViewport.h"
|
||||||
#include "mozilla/layers/TransactionIdAllocator.h"
|
#include "mozilla/layers/TransactionIdAllocator.h"
|
||||||
#include "mozilla/VsyncDispatcher.h"
|
|
||||||
|
|
||||||
class nsPresContext;
|
class nsPresContext;
|
||||||
|
|
||||||
class imgIRequest;
|
class imgIRequest;
|
||||||
class nsINode;
|
|
||||||
class nsIRunnable;
|
class nsIRunnable;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -43,51 +42,8 @@ namespace layout {
|
|||||||
class VsyncChild;
|
class VsyncChild;
|
||||||
} // namespace layout
|
} // namespace layout
|
||||||
|
|
||||||
namespace dom {
|
|
||||||
class Event;
|
|
||||||
} // namespace dom
|
|
||||||
|
|
||||||
} // namespace mozilla
|
} // 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,
|
class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||||
public nsARefreshObserver {
|
public nsARefreshObserver {
|
||||||
using Document = mozilla::dom::Document;
|
using Document = mozilla::dom::Document;
|
||||||
@ -427,7 +383,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
|||||||
EnsureTimerStarted();
|
EnsureTimerStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntersectionObservationAdded() {
|
void EnsureIntersectionObservationsUpdateHappens() {
|
||||||
// This is enough to make sure that UpdateIntersectionObservations runs at
|
// This is enough to make sure that UpdateIntersectionObservations runs at
|
||||||
// least once. This is presumably the intent of step 5 in [1]:
|
// 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>
|
</style>
|
||||||
<div contenteditable="true" spellcheck="false">
|
<div contenteditable="true" spellcheck="false">
|
||||||
xx
|
xx
|
||||||
<span contenteditable="false">
|
<span contenteditable="false">NOT EDITABLE</span>xxx
|
||||||
NOT EDITABLE
|
|
||||||
</span>
|
|
||||||
xxx
|
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
SimpleTest.waitForFocus(function() {
|
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"?>
|
type="text/css"?>
|
||||||
<window onload="runTests()"
|
<window onload="runTests()"
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
<iframe height="200" width="600" type="content"></iframe>
|
<!-- XXXdholbert this wrapper-div and the 'min-height' below are temporary
|
||||||
<iframe height="200" width="600" type="content"></iframe>
|
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">
|
<script type="application/javascript">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
var is = window.opener.wrappedJSObject.is;
|
var is = window.opener.wrappedJSObject.is;
|
||||||
|
@ -164,7 +164,7 @@ support-files = preserve3d_sorting_hit_testing_iframe.html
|
|||||||
[test_preserve3d_sorting_hit_testing2.html]
|
[test_preserve3d_sorting_hit_testing2.html]
|
||||||
support-files = preserve3d_sorting_hit_testing2_iframe.html
|
support-files = preserve3d_sorting_hit_testing2_iframe.html
|
||||||
[test_reftests_with_caret.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 =
|
support-files =
|
||||||
bug106855-1.html
|
bug106855-1.html
|
||||||
bug106855-2.html
|
bug106855-2.html
|
||||||
@ -367,6 +367,11 @@ support-files =
|
|||||||
bug1637476-2-ref.html
|
bug1637476-2-ref.html
|
||||||
bug1637476-3.html
|
bug1637476-3.html
|
||||||
bug1637476-3-ref.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
|
image_rgrg-256x256.png
|
||||||
input-invalid-ref.html
|
input-invalid-ref.html
|
||||||
input-maxlength-invalid-change.html
|
input-maxlength-invalid-change.html
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<script class="testbody" type="application/javascript">
|
<script class="testbody" type="application/javascript">
|
||||||
<!--
|
|
||||||
words = new Array()
|
words = new Array()
|
||||||
|
|
||||||
function expandStringOffsetToWord(data, offset)
|
function expandStringOffsetToWord(data, offset)
|
||||||
@ -35,14 +34,14 @@ function onContextMenu(e)
|
|||||||
|
|
||||||
function startTest()
|
function startTest()
|
||||||
{
|
{
|
||||||
ta = document.getElementById('blah');
|
var ta = document.getElementById('blah');
|
||||||
ta.focus();
|
ta.focus();
|
||||||
ta.selectionStart = ta.selectionEnd = ta.value.length;
|
ta.selectionStart = ta.selectionEnd = ta.value.length;
|
||||||
|
|
||||||
// Note: This test, intentionally or by accident, relies on sending button '0'
|
// Note: This test, intentionally or by accident, relies on sending button '0'
|
||||||
// with contextMenu, which triggers some key-equiv stuff in
|
// with contextMenu, which triggers some key-equiv stuff in
|
||||||
// PresShell::AdjustContextMenuKeyEvent.
|
// PresShell::AdjustContextMenuKeyEvent.
|
||||||
var mouseParams = { type: 'contextmenu', button: 0 };
|
var mouseParams = { type: 'contextmenu', button: 0 };
|
||||||
|
|
||||||
/* Put cursor at start and middle of "sheep" */
|
/* Put cursor at start and middle of "sheep" */
|
||||||
synthesizeKey("KEY_ArrowUp")
|
synthesizeKey("KEY_ArrowUp")
|
||||||
@ -79,7 +78,6 @@ var mouseParams = { type: 'contextmenu', button: 0 };
|
|||||||
|
|
||||||
SimpleTest.waitForExplicitFinish()
|
SimpleTest.waitForExplicitFinish()
|
||||||
SimpleTest.waitForFocus(startTest)
|
SimpleTest.waitForFocus(startTest)
|
||||||
-->
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=370436">Mozilla Bug 370436</a></p>
|
<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">
|
<body id="body" onload="setTimeout(startTest, 0)" style="margin:0; width:100%; height:100%; overflow:hidden">
|
||||||
<p id="display"></p>
|
<p id="display"></p>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<!-- XXX Though B2G isn't supported anymore, we probably want to keep this
|
<!-- We make the `t` target shorter than normal in case because we test the
|
||||||
test's B2G special-cases around, and just make them apply to Android.
|
bottom edge fluffing on this element, and the test page may be hosted
|
||||||
(We may need to do so, for this test to be runnable on Android...?)
|
inside a short iframe in the test harness on some platforms.
|
||||||
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
|
|
||||||
-->
|
-->
|
||||||
<div class="target" style="height:80px" id="t" onmousedown="x=1"></div>
|
<div class="target" style="height:80px" id="t" onmousedown="x=1"></div>
|
||||||
|
|
||||||
@ -77,7 +73,14 @@ function startTest() {
|
|||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
let oldResolution = 1.0;
|
||||||
|
|
||||||
function endTest() {
|
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();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,15 +106,22 @@ function setShowing(id, show) {
|
|||||||
var mm;
|
var mm;
|
||||||
function runTest() {
|
function runTest() {
|
||||||
let resolution = 1;
|
let resolution = 1;
|
||||||
if (SpecialPowers.Services.appinfo.name == "B2G") {
|
if (navigator.appVersion.includes("Android")) {
|
||||||
// This test runs on B2G as well, zoomed out. Therefore we need to account
|
// 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
|
// for the resolution as well, because the fluff area is relative to screen
|
||||||
// pixels rather than CSS pixels.
|
// pixels rather than CSS pixels.
|
||||||
let out = {};
|
resolution = topUtils.getResolution();
|
||||||
SpecialPowers.getDOMWindowUtils(window.top).getResolution(out);
|
// Make sure we were actually able to zoom out to the desired level.
|
||||||
resolution = 1.0 / out.value;
|
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");
|
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
|
// Test basic functionality: clicks sufficiently close to the element
|
||||||
|
@ -274,6 +274,10 @@ var tests = [
|
|||||||
[ 'bug1637476-1.html' , 'bug1637476-1-ref.html' ] ,
|
[ 'bug1637476-1.html' , 'bug1637476-1-ref.html' ] ,
|
||||||
[ 'bug1637476-2.html' , 'bug1637476-2-ref.html' ] ,
|
[ 'bug1637476-2.html' , 'bug1637476-2-ref.html' ] ,
|
||||||
[ 'bug1637476-3.html' , 'bug1637476-3-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({'clear': [['layout.accessiblecaret.enabled_on_touch']]}, nextTest);} ,
|
||||||
function() {SpecialPowers.pushPrefEnv({'set': [['accessibility.browsewithcaret', true]]}, nextTest);} ,
|
function() {SpecialPowers.pushPrefEnv({'set': [['accessibility.browsewithcaret', true]]}, nextTest);} ,
|
||||||
[ 'bug1529492-1.html' , 'bug1529492-1-ref.html' ] ,
|
[ 'bug1529492-1.html' , 'bug1529492-1-ref.html' ] ,
|
||||||
|
@ -39,7 +39,6 @@ LOCAL_INCLUDES += [
|
|||||||
'/dom/media',
|
'/dom/media',
|
||||||
'/dom/offline',
|
'/dom/offline',
|
||||||
'/dom/storage',
|
'/dom/storage',
|
||||||
'/dom/svg',
|
|
||||||
'/dom/xbl',
|
'/dom/xbl',
|
||||||
'/dom/xslt/base',
|
'/dom/xslt/base',
|
||||||
'/dom/xslt/xml',
|
'/dom/xslt/xml',
|
||||||
|
@ -128,15 +128,14 @@ nsContentDLF::CreateInstance(const char* aCommand, nsIChannel* aChannel,
|
|||||||
|
|
||||||
if (knownType) {
|
if (knownType) {
|
||||||
viewSourceChannel->SetContentType(type);
|
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.
|
// 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;
|
contentType = type;
|
||||||
} else {
|
} else {
|
||||||
viewSourceChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
|
viewSourceChannel->SetContentType(nsLiteralCString(TEXT_PLAIN));
|
||||||
}
|
}
|
||||||
} else if (aContentType.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) {
|
} else if (aContentType.EqualsLiteral(VIEWSOURCE_CONTENT_TYPE)) {
|
||||||
aChannel->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
|
aChannel->SetContentType(nsLiteralCString(TEXT_PLAIN));
|
||||||
contentType = TEXT_PLAIN;
|
contentType = TEXT_PLAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +204,7 @@ nsContentDLF::CreateInstance(const char* aCommand, nsIChannel* aChannel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try image types
|
// Try image types
|
||||||
if (IsImageContentType(contentType.get())) {
|
if (IsImageContentType(contentType)) {
|
||||||
return CreateDocument(
|
return CreateDocument(
|
||||||
aCommand, aChannel, aLoadGroup, aContainer,
|
aCommand, aChannel, aLoadGroup, aContainer,
|
||||||
[]() -> already_AddRefed<Document> {
|
[]() -> already_AddRefed<Document> {
|
||||||
@ -266,7 +265,7 @@ already_AddRefed<Document> nsContentDLF::CreateBlankDocument(
|
|||||||
|
|
||||||
// initialize
|
// initialize
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank"));
|
NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -390,6 +389,6 @@ nsresult nsContentDLF::CreateXULDocument(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsContentDLF::IsImageContentType(const char* aContentType) {
|
bool nsContentDLF::IsImageContentType(const nsACString& aContentType) {
|
||||||
return imgLoader::SupportImageWithMimeType(aContentType);
|
return imgLoader::SupportImageWithMimeType(aContentType);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class nsContentDLF final : public nsIDocumentLoaderFactory {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static nsresult EnsureUAStyleSheet();
|
static nsresult EnsureUAStyleSheet();
|
||||||
static bool IsImageContentType(const char* aContentType);
|
static bool IsImageContentType(const nsACString&);
|
||||||
};
|
};
|
||||||
|
|
||||||
nsresult NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult);
|
nsresult NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult);
|
||||||
|
@ -51,8 +51,7 @@
|
|||||||
#include "nsFocusManager.h"
|
#include "nsFocusManager.h"
|
||||||
#include "nsListControlFrame.h"
|
#include "nsListControlFrame.h"
|
||||||
#include "mozilla/dom/HTMLInputElement.h"
|
#include "mozilla/dom/HTMLInputElement.h"
|
||||||
#include "SVGElementFactory.h"
|
#include "mozilla/dom/SVGElementFactory.h"
|
||||||
#include "nsSVGUtils.h"
|
|
||||||
#include "nsMathMLAtoms.h"
|
#include "nsMathMLAtoms.h"
|
||||||
#include "nsMathMLOperators.h"
|
#include "nsMathMLOperators.h"
|
||||||
#include "Navigator.h"
|
#include "Navigator.h"
|
||||||
@ -123,6 +122,7 @@
|
|||||||
#include "mozilla/dom/quota/ActorsParent.h"
|
#include "mozilla/dom/quota/ActorsParent.h"
|
||||||
#include "mozilla/dom/localstorage/ActorsParent.h"
|
#include "mozilla/dom/localstorage/ActorsParent.h"
|
||||||
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
||||||
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsThreadManager.h"
|
#include "nsThreadManager.h"
|
||||||
#include "mozilla/css/ImageLoader.h"
|
#include "mozilla/css/ImageLoader.h"
|
||||||
#include "gfxUserFontSet.h"
|
#include "gfxUserFontSet.h"
|
||||||
@ -305,7 +305,6 @@ void nsLayoutStatics::Shutdown() {
|
|||||||
|
|
||||||
if (XRE_IsParentProcess() || XRE_IsContentProcess()) {
|
if (XRE_IsParentProcess() || XRE_IsContentProcess()) {
|
||||||
ShutdownServo();
|
ShutdownServo();
|
||||||
URLExtraData::ReleaseDummy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::dom::AbstractRange::Shutdown();
|
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 1600207.html
|
||||||
load 1600367.html
|
load 1600367.html
|
||||||
load 1617753.html
|
load 1617753.html
|
||||||
|
load 1679471.html
|
||||||
load 1690166-1.html
|
load 1690166-1.html
|
||||||
load 1690166-2.html
|
load 1690166-2.html
|
||||||
|
@ -2,52 +2,51 @@
|
|||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
with Files('**'):
|
with Files("**"):
|
||||||
BUG_COMPONENT = ('Core', 'Layout: Form Controls')
|
BUG_COMPONENT = ("Core", "Layout: Form Controls")
|
||||||
|
|
||||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
MOCHITEST_MANIFESTS += ["test/mochitest.ini"]
|
||||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
MOCHITEST_CHROME_MANIFESTS += ["test/chrome.ini"]
|
||||||
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'nsIFormControlFrame.h',
|
"nsIFormControlFrame.h",
|
||||||
'nsISelectControlFrame.h',
|
"nsISelectControlFrame.h",
|
||||||
'nsITextControlFrame.h',
|
"nsITextControlFrame.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'nsButtonFrameRenderer.cpp',
|
"nsButtonFrameRenderer.cpp",
|
||||||
'nsCheckboxRadioFrame.cpp',
|
"nsCheckboxRadioFrame.cpp",
|
||||||
'nsColorControlFrame.cpp',
|
"nsColorControlFrame.cpp",
|
||||||
'nsComboboxControlFrame.cpp',
|
"nsComboboxControlFrame.cpp",
|
||||||
'nsDateTimeControlFrame.cpp',
|
"nsDateTimeControlFrame.cpp",
|
||||||
'nsFieldSetFrame.cpp',
|
"nsFieldSetFrame.cpp",
|
||||||
'nsFileControlFrame.cpp',
|
"nsFileControlFrame.cpp",
|
||||||
'nsGfxButtonControlFrame.cpp',
|
"nsGfxButtonControlFrame.cpp",
|
||||||
'nsHTMLButtonControlFrame.cpp',
|
"nsHTMLButtonControlFrame.cpp",
|
||||||
'nsImageControlFrame.cpp',
|
"nsImageControlFrame.cpp",
|
||||||
'nsLegendFrame.cpp',
|
"nsListControlFrame.cpp",
|
||||||
'nsListControlFrame.cpp',
|
"nsMeterFrame.cpp",
|
||||||
'nsMeterFrame.cpp',
|
"nsNumberControlFrame.cpp",
|
||||||
'nsNumberControlFrame.cpp',
|
"nsProgressFrame.cpp",
|
||||||
'nsProgressFrame.cpp',
|
"nsRangeFrame.cpp",
|
||||||
'nsRangeFrame.cpp',
|
"nsSelectsAreaFrame.cpp",
|
||||||
'nsSelectsAreaFrame.cpp',
|
"nsTextControlFrame.cpp",
|
||||||
'nsTextControlFrame.cpp',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = "xul"
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include("/ipc/chromium/chromium-config.mozbuild")
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'../base',
|
"../base",
|
||||||
'../generic',
|
"../generic",
|
||||||
'../painting',
|
"../painting",
|
||||||
'../style',
|
"../style",
|
||||||
'../xul',
|
"../xul",
|
||||||
'/dom/base',
|
"/dom/base",
|
||||||
'/dom/html',
|
"/dom/html",
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
if CONFIG["CC_TYPE"] in ("clang", "gcc"):
|
||||||
CXXFLAGS += ['-Wno-error=shadow']
|
CXXFLAGS += ["-Wno-error=shadow"]
|
||||||
|
@ -49,8 +49,7 @@ nsIFrame* nsButtonFrameRenderer::GetFrame() { return mFrame; }
|
|||||||
void nsButtonFrameRenderer::SetDisabled(bool aDisabled, bool aNotify) {
|
void nsButtonFrameRenderer::SetDisabled(bool aDisabled, bool aNotify) {
|
||||||
dom::Element* element = mFrame->GetContent()->AsElement();
|
dom::Element* element = mFrame->GetContent()->AsElement();
|
||||||
if (aDisabled)
|
if (aDisabled)
|
||||||
element->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, EmptyString(),
|
element->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, u""_ns, aNotify);
|
||||||
aNotify);
|
|
||||||
else
|
else
|
||||||
element->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
|
element->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
|
||||||
}
|
}
|
||||||
@ -89,7 +88,7 @@ class nsDisplayButtonBoxShadowOuter : public nsPaintedDisplayItem {
|
|||||||
nsRect nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder,
|
nsRect nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder,
|
||||||
bool* aSnap) const {
|
bool* aSnap) const {
|
||||||
*aSnap = false;
|
*aSnap = false;
|
||||||
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
|
return mFrame->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
|
void nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
|
||||||
@ -293,8 +292,7 @@ nsRect nsDisplayButtonBorder::GetBounds(nsDisplayListBuilder* aBuilder,
|
|||||||
*aSnap = false;
|
*aSnap = false;
|
||||||
return aBuilder->IsForEventDelivery()
|
return aBuilder->IsForEventDelivery()
|
||||||
? nsRect(ToReferenceFrame(), mFrame->GetSize())
|
? nsRect(ToReferenceFrame(), mFrame->GetSize())
|
||||||
: mFrame->GetVisualOverflowRectRelativeToSelf() +
|
: mFrame->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
|
||||||
ToReferenceFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class nsDisplayButtonForeground final : public nsPaintedDisplayItem {
|
class nsDisplayButtonForeground final : public nsPaintedDisplayItem {
|
||||||
|
@ -65,7 +65,7 @@ nscoord nsCheckboxRadioFrame::GetPrefISize(gfxContext* aRenderingContext) {
|
|||||||
LogicalSize nsCheckboxRadioFrame::ComputeAutoSize(
|
LogicalSize nsCheckboxRadioFrame::ComputeAutoSize(
|
||||||
gfxContext* aRC, WritingMode aWM, const LogicalSize& aCBSize,
|
gfxContext* aRC, WritingMode aWM, const LogicalSize& aCBSize,
|
||||||
nscoord aAvailableISize, const LogicalSize& aMargin,
|
nscoord aAvailableISize, const LogicalSize& aMargin,
|
||||||
const LogicalSize& aBorder, const LogicalSize& aPadding,
|
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
|
||||||
ComputeSizeFlags aFlags) {
|
ComputeSizeFlags aFlags) {
|
||||||
LogicalSize size(aWM, 0, 0);
|
LogicalSize size(aWM, 0, 0);
|
||||||
if (!StyleDisplay()->HasAppearance()) {
|
if (!StyleDisplay()->HasAppearance()) {
|
||||||
@ -74,14 +74,15 @@ LogicalSize nsCheckboxRadioFrame::ComputeAutoSize(
|
|||||||
|
|
||||||
// Note: this call always set the BSize to NS_UNCONSTRAINEDSIZE.
|
// Note: this call always set the BSize to NS_UNCONSTRAINEDSIZE.
|
||||||
size = nsAtomicContainerFrame::ComputeAutoSize(
|
size = nsAtomicContainerFrame::ComputeAutoSize(
|
||||||
aRC, aWM, aCBSize, aAvailableISize, aMargin, aBorder, aPadding, aFlags);
|
aRC, aWM, aCBSize, aAvailableISize, aMargin, aBorderPadding,
|
||||||
|
aSizeOverrides, aFlags);
|
||||||
size.BSize(aWM) = DefaultSize();
|
size.BSize(aWM) = DefaultSize();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord nsCheckboxRadioFrame::GetLogicalBaseline(
|
nscoord nsCheckboxRadioFrame::GetLogicalBaseline(
|
||||||
WritingMode aWritingMode) const {
|
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
|
// For appearance:none we use a standard CSS baseline, i.e. synthesized from
|
||||||
// our margin-box.
|
// our margin-box.
|
||||||
@ -119,8 +120,8 @@ void nsCheckboxRadioFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
|
RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
|
const auto wm = aReflowInput.GetWritingMode();
|
||||||
aReflowInput.ComputedSizeWithBorderPadding());
|
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
|
||||||
|
|
||||||
if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
|
if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
|
||||||
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
|
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
|
||||||
|
@ -46,11 +46,13 @@ class nsCheckboxRadioFrame final : public nsAtomicContainerFrame,
|
|||||||
/**
|
/**
|
||||||
* Our auto size is just intrinsic width and intrinsic height.
|
* Our auto size is just intrinsic width and intrinsic height.
|
||||||
*/
|
*/
|
||||||
virtual mozilla::LogicalSize ComputeAutoSize(
|
mozilla::LogicalSize ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
||||||
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
||||||
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
|
const mozilla::LogicalSize& aMargin,
|
||||||
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
|
const mozilla::LogicalSize& aBorderPadding,
|
||||||
|
const mozilla::StyleSizeOverrides& aSizeOverrides,
|
||||||
|
mozilla::ComputeSizeFlags aFlags) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Respond to a gui event
|
* Respond to a gui event
|
||||||
|
@ -46,7 +46,7 @@ void nsColorControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult nsColorControlFrame::GetFrameName(nsAString& aResult) const {
|
nsresult nsColorControlFrame::GetFrameName(nsAString& aResult) const {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("ColorControl"), aResult);
|
return MakeFrameName(u"ColorControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ nsresult nsColorControlFrame::UpdateColor() {
|
|||||||
|
|
||||||
// Set the background-color CSS property of the swatch element to this color.
|
// Set the background-color CSS property of the swatch element to this color.
|
||||||
return mColorContent->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
|
return mColorContent->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
|
||||||
NS_LITERAL_STRING("background-color:") + color,
|
u"background-color:"_ns + color,
|
||||||
/* aNotify */ true);
|
/* aNotify */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "nsCSSAnonBoxes.h"
|
#include "nsCSSAnonBoxes.h"
|
||||||
#include "nsHTMLParts.h"
|
#include "nsHTMLParts.h"
|
||||||
#include "nsIFormControl.h"
|
#include "nsIFormControl.h"
|
||||||
|
#include "nsILayoutHistoryState.h"
|
||||||
#include "nsNameSpaceManager.h"
|
#include "nsNameSpaceManager.h"
|
||||||
#include "nsListControlFrame.h"
|
#include "nsListControlFrame.h"
|
||||||
#include "nsPIDOMWindow.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
|
// don't even need to cache mDropdownFrame's ascent or anything. If we don't
|
||||||
// need to reflow it, just bail out here.
|
// need to reflow it, just bail out here.
|
||||||
if (!aReflowInput.ShouldReflowAllKids() &&
|
if (!aReflowInput.ShouldReflowAllKids() &&
|
||||||
!NS_SUBTREE_DIRTY(mDropdownFrame)) {
|
!mDropdownFrame->IsSubtreeDirty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,8 +420,8 @@ void nsComboboxControlFrame::ReflowDropdown(nsPresContext* aPresContext,
|
|||||||
// both sets of mComputedBorderPadding.
|
// both sets of mComputedBorderPadding.
|
||||||
nscoord forcedISize =
|
nscoord forcedISize =
|
||||||
aReflowInput.ComputedISize() +
|
aReflowInput.ComputedISize() +
|
||||||
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm) -
|
aReflowInput.ComputedLogicalBorderPadding(wm).IStartEnd(wm) -
|
||||||
kidReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm);
|
kidReflowInput.ComputedLogicalBorderPadding(wm).IStartEnd(wm);
|
||||||
kidReflowInput.SetComputedISize(
|
kidReflowInput.SetComputedISize(
|
||||||
std::max(kidReflowInput.ComputedISize(), forcedISize));
|
std::max(kidReflowInput.ComputedISize(), forcedISize));
|
||||||
|
|
||||||
@ -463,7 +464,8 @@ nsPoint nsComboboxControlFrame::GetCSSTransformTranslation() {
|
|||||||
Matrix transform;
|
Matrix transform;
|
||||||
while (frame) {
|
while (frame) {
|
||||||
nsIFrame* parent;
|
nsIFrame* parent;
|
||||||
Matrix4x4Flagged ctm = frame->GetTransformMatrix(nullptr, &parent);
|
Matrix4x4Flagged ctm = frame->GetTransformMatrix(
|
||||||
|
ViewportType::Layout, RelativeTo{nullptr}, &parent);
|
||||||
Matrix matrix;
|
Matrix matrix;
|
||||||
if (ctm.Is2D(&matrix)) {
|
if (ctm.Is2D(&matrix)) {
|
||||||
transform = transform * matrix;
|
transform = transform * matrix;
|
||||||
@ -566,7 +568,7 @@ void nsComboboxControlFrame::GetAvailableDropdownSpace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
nscoord minBCoord;
|
nscoord minBCoord;
|
||||||
nsPresContext* pc = PresContext()->GetToplevelContentDocumentPresContext();
|
nsPresContext* pc = PresContext()->GetInProcessRootContentDocumentPresContext();
|
||||||
nsIFrame* root = pc ? pc->PresShell()->GetRootFrame() : nullptr;
|
nsIFrame* root = pc ? pc->PresShell()->GetRootFrame() : nullptr;
|
||||||
if (root) {
|
if (root) {
|
||||||
minBCoord = LogicalRect(aWM, root->GetScreenRectInAppUnits(), containerSize)
|
minBCoord = LogicalRect(aWM, root->GetScreenRectInAppUnits(), containerSize)
|
||||||
@ -703,8 +705,8 @@ bool nsComboboxControlFrame::HasDropDownButton() const {
|
|||||||
PresContext()->Theme()->ThemeNeedsComboboxDropmarker());
|
PresContext()->Theme()->ThemeNeedsComboboxDropmarker());
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord nsComboboxControlFrame::GetIntrinsicISize(
|
nscoord nsComboboxControlFrame::GetIntrinsicISize(gfxContext* aRenderingContext,
|
||||||
gfxContext* aRenderingContext, nsLayoutUtils::IntrinsicISizeType aType) {
|
IntrinsicISizeType aType) {
|
||||||
// get the scrollbar width, we'll use this later
|
// get the scrollbar width, we'll use this later
|
||||||
nscoord scrollbarWidth = 0;
|
nscoord scrollbarWidth = 0;
|
||||||
nsPresContext* presContext = PresContext();
|
nsPresContext* presContext = PresContext();
|
||||||
@ -731,14 +733,14 @@ nscoord nsComboboxControlFrame::GetIntrinsicISize(
|
|||||||
nscoord dropdownContentISize;
|
nscoord dropdownContentISize;
|
||||||
bool isUsingOverlayScrollbars =
|
bool isUsingOverlayScrollbars =
|
||||||
LookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) != 0;
|
LookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) != 0;
|
||||||
if (aType == nsLayoutUtils::MIN_ISIZE) {
|
if (aType == IntrinsicISizeType::MinISize) {
|
||||||
dropdownContentISize =
|
dropdownContentISize =
|
||||||
isContainSize ? 0 : mDropdownFrame->GetMinISize(aRenderingContext);
|
isContainSize ? 0 : mDropdownFrame->GetMinISize(aRenderingContext);
|
||||||
if (isUsingOverlayScrollbars) {
|
if (isUsingOverlayScrollbars) {
|
||||||
dropdownContentISize += scrollbarWidth;
|
dropdownContentISize += scrollbarWidth;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NS_ASSERTION(aType == nsLayoutUtils::PREF_ISIZE, "Unexpected type");
|
NS_ASSERTION(aType == IntrinsicISizeType::PrefISize, "Unexpected type");
|
||||||
dropdownContentISize =
|
dropdownContentISize =
|
||||||
isContainSize ? 0 : mDropdownFrame->GetPrefISize(aRenderingContext);
|
isContainSize ? 0 : mDropdownFrame->GetPrefISize(aRenderingContext);
|
||||||
if (isUsingOverlayScrollbars) {
|
if (isUsingOverlayScrollbars) {
|
||||||
@ -762,14 +764,15 @@ nscoord nsComboboxControlFrame::GetIntrinsicISize(
|
|||||||
nscoord nsComboboxControlFrame::GetMinISize(gfxContext* aRenderingContext) {
|
nscoord nsComboboxControlFrame::GetMinISize(gfxContext* aRenderingContext) {
|
||||||
nscoord minISize;
|
nscoord minISize;
|
||||||
DISPLAY_MIN_INLINE_SIZE(this, minISize);
|
DISPLAY_MIN_INLINE_SIZE(this, minISize);
|
||||||
minISize = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::MIN_ISIZE);
|
minISize = GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::MinISize);
|
||||||
return minISize;
|
return minISize;
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord nsComboboxControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
|
nscoord nsComboboxControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
|
||||||
nscoord prefISize;
|
nscoord prefISize;
|
||||||
DISPLAY_PREF_INLINE_SIZE(this, prefISize);
|
DISPLAY_PREF_INLINE_SIZE(this, prefISize);
|
||||||
prefISize = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::PREF_ISIZE);
|
prefISize =
|
||||||
|
GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::PrefISize);
|
||||||
return prefISize;
|
return prefISize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,19 +836,18 @@ void nsComboboxControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
mDisplayISize = aReflowInput.ComputedISize() - buttonISize;
|
mDisplayISize = aReflowInput.ComputedISize() - buttonISize;
|
||||||
|
|
||||||
mMaxDisplayISize =
|
mMaxDisplayISize =
|
||||||
mDisplayISize + aReflowInput.ComputedLogicalPadding().IEnd(wm);
|
mDisplayISize + aReflowInput.ComputedLogicalPadding(wm).IEnd(wm);
|
||||||
|
|
||||||
nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
|
nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
|
||||||
|
|
||||||
// The button should occupy the same space as a scrollbar
|
// The button should occupy the same space as a scrollbar
|
||||||
nsSize containerSize = aDesiredSize.PhysicalSize();
|
nsSize containerSize = aDesiredSize.PhysicalSize();
|
||||||
LogicalRect buttonRect = mButtonFrame->GetLogicalRect(containerSize);
|
LogicalRect buttonRect = mButtonFrame->GetLogicalRect(containerSize);
|
||||||
|
const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(wm);
|
||||||
|
|
||||||
buttonRect.IStart(wm) =
|
buttonRect.IStart(wm) = borderPadding.IStartEnd(wm) + mDisplayISize -
|
||||||
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm) +
|
(borderPadding.IEnd(wm) -
|
||||||
mDisplayISize -
|
aReflowInput.ComputedLogicalPadding(wm).IEnd(wm));
|
||||||
(aReflowInput.ComputedLogicalBorderPadding().IEnd(wm) -
|
|
||||||
aReflowInput.ComputedLogicalPadding().IEnd(wm));
|
|
||||||
buttonRect.ISize(wm) = buttonISize;
|
buttonRect.ISize(wm) = buttonISize;
|
||||||
|
|
||||||
buttonRect.BStart(wm) = this->GetLogicalUsedBorder(wm).BStart(wm);
|
buttonRect.BStart(wm) = this->GetLogicalUsedBorder(wm).BStart(wm);
|
||||||
@ -865,7 +867,7 @@ void nsComboboxControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult nsComboboxControlFrame::GetFrameName(nsAString& aResult) const {
|
nsresult nsComboboxControlFrame::GetFrameName(nsAString& aResult) const {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("ComboboxControl"), aResult);
|
return MakeFrameName(u"ComboboxControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1170,20 +1172,18 @@ nsresult nsComboboxControlFrame::CreateAnonymousContent(
|
|||||||
// make someone to listen to the button. If its pressed by someone like
|
// make someone to listen to the button. If its pressed by someone like
|
||||||
// Accessibility then open or close the combo box.
|
// Accessibility then open or close the combo box.
|
||||||
mButtonListener = new nsComboButtonListener(this);
|
mButtonListener = new nsComboButtonListener(this);
|
||||||
mButtonContent->AddEventListener(NS_LITERAL_STRING("click"), mButtonListener,
|
mButtonContent->AddEventListener(u"click"_ns, mButtonListener, false, false);
|
||||||
false, false);
|
|
||||||
|
|
||||||
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::type, u"button"_ns,
|
||||||
NS_LITERAL_STRING("button"), false);
|
false);
|
||||||
// Set tabindex="-1" so that the button is not tabbable
|
// Set tabindex="-1" so that the button is not tabbable
|
||||||
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::tabindex,
|
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, u"-1"_ns,
|
||||||
NS_LITERAL_STRING("-1"), false);
|
false);
|
||||||
|
|
||||||
WritingMode wm = GetWritingMode();
|
WritingMode wm = GetWritingMode();
|
||||||
if (wm.IsVertical()) {
|
if (wm.IsVertical()) {
|
||||||
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orientation,
|
mButtonContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orientation,
|
||||||
wm.IsVerticalRL() ? NS_LITERAL_STRING("left")
|
wm.IsVerticalRL() ? u"left"_ns : u"right"_ns,
|
||||||
: NS_LITERAL_STRING("right"),
|
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1222,7 +1222,7 @@ class nsComboboxDisplayFrame final : public nsBlockFrame {
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult GetFrameName(nsAString& aResult) const override {
|
nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("ComboboxDisplay"), aResult);
|
return MakeFrameName(u"ComboboxDisplay"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1252,7 +1252,7 @@ void nsComboboxDisplayFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
ReflowInput state(aReflowInput);
|
ReflowInput state(aReflowInput);
|
||||||
WritingMode wm = aReflowInput.GetWritingMode();
|
WritingMode wm = aReflowInput.GetWritingMode();
|
||||||
LogicalMargin bp = state.ComputedLogicalBorderPadding();
|
LogicalMargin bp = state.ComputedLogicalBorderPadding(wm);
|
||||||
if (state.ComputedBSize() == NS_UNCONSTRAINEDSIZE) {
|
if (state.ComputedBSize() == NS_UNCONSTRAINEDSIZE) {
|
||||||
float inflation = nsLayoutUtils::FontSizeInflationFor(mComboBox);
|
float inflation = nsLayoutUtils::FontSizeInflationFor(mComboBox);
|
||||||
// We intentionally use the combobox frame's style here, which has
|
// We intentionally use the combobox frame's style here, which has
|
||||||
@ -1339,6 +1339,10 @@ nsIFrame* nsComboboxControlFrame::CreateFrameForDisplayNode() {
|
|||||||
return mDisplayFrame;
|
return mDisplayFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIScrollableFrame* nsComboboxControlFrame::GetScrollTargetFrame() const {
|
||||||
|
return do_QueryFrame(mDropdownFrame);
|
||||||
|
}
|
||||||
|
|
||||||
void nsComboboxControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
void nsComboboxControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||||
PostDestroyData& aPostDestroyData) {
|
PostDestroyData& aPostDestroyData) {
|
||||||
if (sFocused == this) {
|
if (sFocused == this) {
|
||||||
@ -1570,9 +1574,8 @@ nsComboboxControlFrame::OnOptionSelected(int32_t aIndex, bool aSelected) {
|
|||||||
|
|
||||||
void nsComboboxControlFrame::FireValueChangeEvent() {
|
void nsComboboxControlFrame::FireValueChangeEvent() {
|
||||||
// Fire ValueChange event to indicate data value of combo box has changed
|
// Fire ValueChange event to indicate data value of combo box has changed
|
||||||
nsContentUtils::AddScriptRunner(
|
nsContentUtils::AddScriptRunner(new AsyncEventDispatcher(
|
||||||
new AsyncEventDispatcher(mContent, NS_LITERAL_STRING("ValueChange"),
|
mContent, u"ValueChange"_ns, CanBubble::eYes, ChromeOnlyDispatch::eNo));
|
||||||
CanBubble::eYes, ChromeOnlyDispatch::eNo));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsComboboxControlFrame::OnContentReset() {
|
void nsComboboxControlFrame::OnContentReset() {
|
||||||
|
@ -100,9 +100,7 @@ class nsComboboxControlFrame final : public nsBlockFrame,
|
|||||||
aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
|
aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual nsIScrollableFrame* GetScrollTargetFrame() override {
|
virtual nsIScrollableFrame* GetScrollTargetFrame() const override;
|
||||||
return do_QueryFrame(mDropdownFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
virtual nsresult GetFrameName(nsAString& aResult) const override;
|
virtual nsresult GetFrameName(nsAString& aResult) const override;
|
||||||
@ -238,7 +236,7 @@ class nsComboboxControlFrame final : public nsBlockFrame,
|
|||||||
|
|
||||||
// Helper for GetMinISize/GetPrefISize
|
// Helper for GetMinISize/GetPrefISize
|
||||||
nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
|
nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
|
||||||
nsLayoutUtils::IntrinsicISizeType aType);
|
mozilla::IntrinsicISizeType aType);
|
||||||
|
|
||||||
class RedisplayTextEvent : public mozilla::Runnable {
|
class RedisplayTextEvent : public mozilla::Runnable {
|
||||||
public:
|
public:
|
||||||
|
@ -48,7 +48,7 @@ nscoord nsDateTimeControlFrame::GetMinISize(gfxContext* aRenderingContext) {
|
|||||||
nsIFrame* kid = mFrames.FirstChild();
|
nsIFrame* kid = mFrames.FirstChild();
|
||||||
if (kid) { // display:none?
|
if (kid) { // display:none?
|
||||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
|
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
|
||||||
nsLayoutUtils::MIN_ISIZE);
|
IntrinsicISizeType::MinISize);
|
||||||
} else {
|
} else {
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
@ -62,8 +62,8 @@ nscoord nsDateTimeControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
|
|||||||
|
|
||||||
nsIFrame* kid = mFrames.FirstChild();
|
nsIFrame* kid = mFrames.FirstChild();
|
||||||
if (kid) { // display:none?
|
if (kid) { // display:none?
|
||||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
|
result = nsLayoutUtils::IntrinsicForContainer(
|
||||||
nsLayoutUtils::PREF_ISIZE);
|
aRenderingContext, kid, IntrinsicISizeType::PrefISize);
|
||||||
} else {
|
} else {
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
@ -97,23 +97,20 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
// Figure out our border-box sizes as well (by adding borderPadding to
|
// Figure out our border-box sizes as well (by adding borderPadding to
|
||||||
// content-box sizes):
|
// content-box sizes):
|
||||||
|
const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(myWM);
|
||||||
const nscoord borderBoxISize =
|
const nscoord borderBoxISize =
|
||||||
contentBoxISize +
|
contentBoxISize + borderPadding.IStartEnd(myWM);
|
||||||
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(myWM);
|
|
||||||
|
|
||||||
nscoord borderBoxBSize;
|
nscoord borderBoxBSize;
|
||||||
if (contentBoxBSize != NS_UNCONSTRAINEDSIZE) {
|
if (contentBoxBSize != NS_UNCONSTRAINEDSIZE) {
|
||||||
borderBoxBSize =
|
borderBoxBSize = contentBoxBSize + borderPadding.BStartEnd(myWM);
|
||||||
contentBoxBSize +
|
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
|
|
||||||
} // else, we'll figure out borderBoxBSize after we resolve contentBoxBSize.
|
} // else, we'll figure out borderBoxBSize after we resolve contentBoxBSize.
|
||||||
|
|
||||||
nsIFrame* inputAreaFrame = mFrames.FirstChild();
|
nsIFrame* inputAreaFrame = mFrames.FirstChild();
|
||||||
if (!inputAreaFrame) { // display:none?
|
if (!inputAreaFrame) { // display:none?
|
||||||
if (contentBoxBSize == NS_UNCONSTRAINEDSIZE) {
|
if (contentBoxBSize == NS_UNCONSTRAINEDSIZE) {
|
||||||
contentBoxBSize = 0;
|
contentBoxBSize = 0;
|
||||||
borderBoxBSize =
|
borderBoxBSize = borderPadding.BStartEnd(myWM);
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ReflowOutput childDesiredSize(aReflowInput);
|
ReflowOutput childDesiredSize(aReflowInput);
|
||||||
@ -122,27 +119,23 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
LogicalSize availSize = aReflowInput.ComputedSize(wm);
|
LogicalSize availSize = aReflowInput.ComputedSize(wm);
|
||||||
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
||||||
|
|
||||||
ReflowInput childReflowOuput(aPresContext, aReflowInput, inputAreaFrame,
|
ReflowInput childReflowInput(aPresContext, aReflowInput, inputAreaFrame,
|
||||||
availSize);
|
availSize);
|
||||||
|
|
||||||
// Convert input area margin into my own writing-mode (in case it differs):
|
// Convert input area margin into my own writing-mode (in case it differs):
|
||||||
LogicalMargin childMargin =
|
LogicalMargin childMargin = childReflowInput.ComputedLogicalMargin(myWM);
|
||||||
childReflowOuput.ComputedLogicalMargin().ConvertTo(myWM, wm);
|
|
||||||
|
|
||||||
// offsets of input area frame within this frame:
|
// offsets of input area frame within this frame:
|
||||||
LogicalPoint childOffset(
|
LogicalPoint childOffset(
|
||||||
myWM,
|
myWM, borderPadding.IStart(myWM) + childMargin.IStart(myWM),
|
||||||
aReflowInput.ComputedLogicalBorderPadding().IStart(myWM) +
|
borderPadding.BStart(myWM) + childMargin.BStart(myWM));
|
||||||
childMargin.IStart(myWM),
|
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStart(myWM) +
|
|
||||||
childMargin.BStart(myWM));
|
|
||||||
|
|
||||||
nsReflowStatus childStatus;
|
nsReflowStatus childStatus;
|
||||||
// We initially reflow the child with a dummy containerSize; positioning
|
// We initially reflow the child with a dummy containerSize; positioning
|
||||||
// will be fixed later.
|
// will be fixed later.
|
||||||
const nsSize dummyContainerSize;
|
const nsSize dummyContainerSize;
|
||||||
ReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
|
ReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
|
||||||
childReflowOuput, myWM, childOffset, dummyContainerSize,
|
childReflowInput, myWM, childOffset, dummyContainerSize,
|
||||||
ReflowChildFlags::Default, childStatus);
|
ReflowChildFlags::Default, childStatus);
|
||||||
MOZ_ASSERT(childStatus.IsFullyComplete(),
|
MOZ_ASSERT(childStatus.IsFullyComplete(),
|
||||||
"We gave our child unconstrained available block-size, "
|
"We gave our child unconstrained available block-size, "
|
||||||
@ -165,9 +158,7 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
NS_CSS_MINMAX(contentBoxBSize, aReflowInput.ComputedMinBSize(),
|
NS_CSS_MINMAX(contentBoxBSize, aReflowInput.ComputedMinBSize(),
|
||||||
aReflowInput.ComputedMaxBSize());
|
aReflowInput.ComputedMaxBSize());
|
||||||
|
|
||||||
borderBoxBSize =
|
borderBoxBSize = contentBoxBSize + borderPadding.BStartEnd(myWM);
|
||||||
contentBoxBSize +
|
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(myWM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Center child in block axis
|
// Center child in block axis
|
||||||
@ -180,10 +171,11 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
// Place the child
|
// Place the child
|
||||||
FinishReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
|
FinishReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
|
||||||
&childReflowOuput, myWM, childOffset, borderBoxSize,
|
&childReflowInput, myWM, childOffset, borderBoxSize,
|
||||||
ReflowChildFlags::Default);
|
ReflowChildFlags::Default);
|
||||||
|
|
||||||
if (!aReflowInput.mStyleDisplay->IsContainLayout()) {
|
if (!aReflowInput.mStyleDisplay->IsContainLayout() &&
|
||||||
|
childDesiredSize.BlockStartAscent() != ReflowOutput::ASK_FOR_BASELINE) {
|
||||||
nsSize contentBoxSize =
|
nsSize contentBoxSize =
|
||||||
LogicalSize(myWM, contentBoxISize, contentBoxBSize)
|
LogicalSize(myWM, contentBoxISize, contentBoxBSize)
|
||||||
.GetPhysicalSize(myWM);
|
.GetPhysicalSize(myWM);
|
||||||
@ -191,7 +183,7 @@ void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
childDesiredSize.BlockStartAscent() +
|
childDesiredSize.BlockStartAscent() +
|
||||||
inputAreaFrame->BStart(aReflowInput.GetWritingMode(),
|
inputAreaFrame->BStart(aReflowInput.GetWritingMode(),
|
||||||
contentBoxSize));
|
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);
|
LogicalSize logicalDesiredSize(myWM, borderBoxISize, borderBoxBSize);
|
||||||
|
@ -41,7 +41,7 @@ class nsDateTimeControlFrame final : public nsContainerFrame {
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult GetFrameName(nsAString& aResult) const override {
|
nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("DateTimeControl"), aResult);
|
return MakeFrameName(u"DateTimeControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -11,14 +11,18 @@
|
|||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "nsBlockFrame.h"
|
||||||
#include "nsCSSAnonBoxes.h"
|
#include "nsCSSAnonBoxes.h"
|
||||||
|
#include "nsCSSFrameConstructor.h"
|
||||||
#include "nsCSSRendering.h"
|
#include "nsCSSRendering.h"
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsIFrameInlines.h"
|
#include "nsIFrameInlines.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsLegendFrame.h"
|
|
||||||
#include "nsStyleConsts.h"
|
#include "nsStyleConsts.h"
|
||||||
|
#ifdef MOZ_BUILD_WEBRENDER
|
||||||
|
# include "mozilla/webrender/WebRenderAPI.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::gfx;
|
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
|
// nsDisplayBorder has here, but keeping things in sync would be a pain, and
|
||||||
// this code is not typically performance-sensitive.
|
// this code is not typically performance-sensitive.
|
||||||
*aSnap = false;
|
*aSnap = false;
|
||||||
return Frame()->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
|
return Frame()->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_BUILD_WEBRENDER
|
#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
|
// We need to clip out the part of the border where the legend would go
|
||||||
auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
||||||
auto layoutRect = wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
|
auto layoutRect = wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
|
||||||
frame->GetVisualOverflowRectRelativeToSelf() + offset,
|
frame->InkOverflowRectRelativeToSelf() + offset,
|
||||||
appUnitsPerDevPixel));
|
appUnitsPerDevPixel));
|
||||||
|
|
||||||
wr::ComplexClipRegion region;
|
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
|
// 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
|
// 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
|
// 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
|
// by transforms), because we can have borders sticking outside our border
|
||||||
// box (e.g. due to border-image-outset).
|
// box (e.g. due to border-image-outset).
|
||||||
RefPtr<PathBuilder> pathBuilder =
|
RefPtr<PathBuilder> pathBuilder =
|
||||||
drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
|
drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
|
||||||
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||||
AppendRectToPath(
|
AppendRectToPath(pathBuilder,
|
||||||
pathBuilder,
|
NSRectToSnappedRect(InkOverflowRectRelativeToSelf() + aPt,
|
||||||
NSRectToSnappedRect(GetVisualOverflowRectRelativeToSelf() + aPt,
|
appUnitsPerDevPixel, *drawTarget),
|
||||||
appUnitsPerDevPixel, *drawTarget),
|
true);
|
||||||
true);
|
|
||||||
AppendRectToPath(
|
AppendRectToPath(
|
||||||
pathBuilder,
|
pathBuilder,
|
||||||
NSRectToSnappedRect(legendRect, appUnitsPerDevPixel, *drawTarget),
|
NSRectToSnappedRect(legendRect, appUnitsPerDevPixel, *drawTarget),
|
||||||
@ -343,8 +346,8 @@ image::ImgDrawResult nsFieldSetFrame::PaintBorder(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord nsFieldSetFrame::GetIntrinsicISize(
|
nscoord nsFieldSetFrame::GetIntrinsicISize(gfxContext* aRenderingContext,
|
||||||
gfxContext* aRenderingContext, nsLayoutUtils::IntrinsicISizeType aType) {
|
IntrinsicISizeType aType) {
|
||||||
nscoord legendWidth = 0;
|
nscoord legendWidth = 0;
|
||||||
nscoord contentWidth = 0;
|
nscoord contentWidth = 0;
|
||||||
if (!StyleDisplay()->IsContainSize()) {
|
if (!StyleDisplay()->IsContainSize()) {
|
||||||
@ -371,7 +374,7 @@ nscoord nsFieldSetFrame::GetMinISize(gfxContext* aRenderingContext) {
|
|||||||
nscoord result = 0;
|
nscoord result = 0;
|
||||||
DISPLAY_MIN_INLINE_SIZE(this, result);
|
DISPLAY_MIN_INLINE_SIZE(this, result);
|
||||||
|
|
||||||
result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::MIN_ISIZE);
|
result = GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::MinISize);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +382,7 @@ nscoord nsFieldSetFrame::GetPrefISize(gfxContext* aRenderingContext) {
|
|||||||
nscoord result = 0;
|
nscoord result = 0;
|
||||||
DISPLAY_PREF_INLINE_SIZE(this, result);
|
DISPLAY_PREF_INLINE_SIZE(this, result);
|
||||||
|
|
||||||
result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::PREF_ISIZE);
|
result = GetIntrinsicISize(aRenderingContext, IntrinsicISizeType::PrefISize);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +391,7 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
ReflowOutput& aDesiredSize,
|
ReflowOutput& aDesiredSize,
|
||||||
const ReflowInput& aReflowInput,
|
const ReflowInput& aReflowInput,
|
||||||
nsReflowStatus& aStatus) {
|
nsReflowStatus& aStatus) {
|
||||||
using LegendAlignValue = HTMLLegendElement::LegendAlignValue;
|
using LegendAlignValue = mozilla::dom::HTMLLegendElement::LegendAlignValue;
|
||||||
|
|
||||||
MarkInReflow();
|
MarkInReflow();
|
||||||
DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
|
DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
|
||||||
@ -397,7 +400,7 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
NS_WARNING_ASSERTION(aReflowInput.ComputedISize() != NS_UNCONSTRAINEDSIZE,
|
NS_WARNING_ASSERTION(aReflowInput.ComputedISize() != NS_UNCONSTRAINEDSIZE,
|
||||||
"Should have a precomputed inline-size!");
|
"Should have a precomputed inline-size!");
|
||||||
|
|
||||||
nsOverflowAreas ocBounds;
|
OverflowAreas ocBounds;
|
||||||
nsReflowStatus ocStatus;
|
nsReflowStatus ocStatus;
|
||||||
auto* prevInFlow = static_cast<nsFieldSetFrame*>(GetPrevInFlow());
|
auto* prevInFlow = static_cast<nsFieldSetFrame*>(GetPrevInFlow());
|
||||||
if (prevInFlow) {
|
if (prevInFlow) {
|
||||||
@ -427,15 +430,15 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
reflowInner = inner != nullptr;
|
reflowInner = inner != nullptr;
|
||||||
reflowLegend = legend != nullptr;
|
reflowLegend = legend != nullptr;
|
||||||
} else {
|
} else {
|
||||||
reflowInner = inner && NS_SUBTREE_DIRTY(inner);
|
reflowInner = inner && inner->IsSubtreeDirty();
|
||||||
reflowLegend = legend && NS_SUBTREE_DIRTY(legend);
|
reflowLegend = legend && legend->IsSubtreeDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note |this| frame applies borders but not any padding. Our anonymous
|
// @note |this| frame applies borders but not any padding. Our anonymous
|
||||||
// inner frame applies the padding (but not borders).
|
// inner frame applies the padding (but not borders).
|
||||||
const auto wm = GetWritingMode();
|
const auto wm = GetWritingMode();
|
||||||
LogicalMargin border = aReflowInput.ComputedLogicalBorderPadding() -
|
LogicalMargin border = aReflowInput.ComputedLogicalBorderPadding(wm) -
|
||||||
aReflowInput.ComputedLogicalPadding();
|
aReflowInput.ComputedLogicalPadding(wm);
|
||||||
auto skipSides = PreReflowBlockLevelLogicalSkipSides();
|
auto skipSides = PreReflowBlockLevelLogicalSkipSides();
|
||||||
border.ApplySkipSides(skipSides);
|
border.ApplySkipSides(skipSides);
|
||||||
LogicalSize availSize(wm, aReflowInput.ComputedSize().ISize(wm),
|
LogicalSize availSize(wm, aReflowInput.ComputedSize().ISize(wm),
|
||||||
@ -447,8 +450,15 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
if (legend) {
|
if (legend) {
|
||||||
const auto legendWM = legend->GetWritingMode();
|
const auto legendWM = legend->GetWritingMode();
|
||||||
LogicalSize legendAvailSize = availSize.ConvertTo(legendWM, wm);
|
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,
|
legendReflowInput.emplace(aPresContext, aReflowInput, legend,
|
||||||
legendAvailSize);
|
legendAvailSize, Nothing(), initFlags,
|
||||||
|
sizeOverrides, sizeFlags);
|
||||||
}
|
}
|
||||||
const bool avoidBreakInside = ShouldAvoidBreakInside(aReflowInput);
|
const bool avoidBreakInside = ShouldAvoidBreakInside(aReflowInput);
|
||||||
if (reflowLegend) {
|
if (reflowLegend) {
|
||||||
@ -548,7 +558,8 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
(LogicalSize(wm, 0, mLegendSpace) + border.Size(wm)).GetPhysicalSize(wm);
|
(LogicalSize(wm, 0, mLegendSpace) + border.Size(wm)).GetPhysicalSize(wm);
|
||||||
if (reflowInner) {
|
if (reflowInner) {
|
||||||
LogicalSize innerAvailSize = availSize;
|
LogicalSize innerAvailSize = availSize;
|
||||||
innerAvailSize.ISize(wm) = aReflowInput.ComputedSizeWithPadding().ISize(wm);
|
innerAvailSize.ISize(wm) =
|
||||||
|
aReflowInput.ComputedSizeWithPadding(wm).ISize(wm);
|
||||||
nscoord remainingComputedBSize = aReflowInput.ComputedBSize();
|
nscoord remainingComputedBSize = aReflowInput.ComputedBSize();
|
||||||
if (prevInFlow && remainingComputedBSize != NS_UNCONSTRAINEDSIZE) {
|
if (prevInFlow && remainingComputedBSize != NS_UNCONSTRAINEDSIZE) {
|
||||||
// Subtract the consumed BSize associated with the legend.
|
// Subtract the consumed BSize associated with the legend.
|
||||||
@ -565,7 +576,8 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
StyleBoxDecorationBreak::Clone &&
|
StyleBoxDecorationBreak::Clone &&
|
||||||
(aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
|
(aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
|
||||||
remainingComputedBSize +
|
remainingComputedBSize +
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm) >=
|
aReflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(
|
||||||
|
wm) >=
|
||||||
availSize.BSize(wm))) {
|
availSize.BSize(wm))) {
|
||||||
innerAvailSize.BSize(wm) -= border.BEnd(wm);
|
innerAvailSize.BSize(wm) -= border.BEnd(wm);
|
||||||
}
|
}
|
||||||
@ -573,10 +585,11 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
}
|
}
|
||||||
ReflowInput kidReflowInput(aPresContext, aReflowInput, inner,
|
ReflowInput kidReflowInput(aPresContext, aReflowInput, inner,
|
||||||
innerAvailSize, Nothing(),
|
innerAvailSize, Nothing(),
|
||||||
ReflowInput::CALLER_WILL_INIT);
|
ReflowInput::InitFlag::CallerWillInit);
|
||||||
// Override computed padding, in case it's percentage padding
|
// Override computed padding, in case it's percentage padding
|
||||||
kidReflowInput.Init(aPresContext, Nothing(), nullptr,
|
kidReflowInput.Init(
|
||||||
&aReflowInput.ComputedPhysicalPadding());
|
aPresContext, Nothing(), Nothing(),
|
||||||
|
Some(aReflowInput.ComputedLogicalPadding(inner->GetWritingMode())));
|
||||||
if (kidReflowInput.mFlags.mIsTopOfPage) {
|
if (kidReflowInput.mFlags.mIsTopOfPage) {
|
||||||
// Prevent break-before from |inner| if we have a legend.
|
// Prevent break-before from |inner| if we have a legend.
|
||||||
kidReflowInput.mFlags.mIsTopOfPage = !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
|
// The legend is positioned inline-wards within the inner's content rect
|
||||||
// (so that padding on the fieldset affects the legend position).
|
// (so that padding on the fieldset affects the legend position).
|
||||||
LogicalRect innerContentRect = contentRect;
|
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
|
// If the inner content rect is larger than the legend, we can align the
|
||||||
// legend.
|
// legend.
|
||||||
if (innerContentRect.ISize(wm) > mLegendRect.ISize(wm)) {
|
if (innerContentRect.ISize(wm) > mLegendRect.ISize(wm)) {
|
||||||
// NOTE legend @align values are: left/right/center
|
// NOTE legend @align values are: left/right/center
|
||||||
// GetLogicalAlign converts left/right to start/end for the given WM.
|
// GetLogicalAlign converts left/right to start/end for the given WM.
|
||||||
// @see HTMLLegendElement::ParseAttribute, nsLegendFrame::GetLogicalAlign
|
// @see HTMLLegendElement::ParseAttribute/LogicalAlign
|
||||||
LegendAlignValue align =
|
auto* legendElement =
|
||||||
static_cast<nsLegendFrame*>(legend->GetContentInsertionFrame())
|
dom::HTMLLegendElement::FromNode(legend->GetContent());
|
||||||
->GetLogicalAlign(wm);
|
switch (legendElement->LogicalAlign(wm)) {
|
||||||
switch (align) {
|
|
||||||
case LegendAlignValue::InlineEnd:
|
case LegendAlignValue::InlineEnd:
|
||||||
mLegendRect.IStart(wm) =
|
mLegendRect.IStart(wm) =
|
||||||
innerContentRect.IEnd(wm) - mLegendRect.ISize(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,
|
// 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).
|
// so we need to convert offsets before applying them to it (bug 1134534).
|
||||||
LogicalMargin offsets =
|
LogicalMargin offsets = legendReflowInput->ComputedLogicalOffsets(wm);
|
||||||
legendReflowInput->ComputedLogicalOffsets().ConvertTo(
|
|
||||||
wm, legendReflowInput->GetWritingMode());
|
|
||||||
ReflowInput::ApplyRelativePositioning(legend, wm, offsets, &actualLegendPos,
|
ReflowInput::ApplyRelativePositioning(legend, wm, offsets, &actualLegendPos,
|
||||||
containerSize);
|
containerSize);
|
||||||
|
|
||||||
@ -744,7 +754,7 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
: aReflowInput.ComputedBSize();
|
: aReflowInput.ComputedBSize();
|
||||||
finalSize.BSize(wm) =
|
finalSize.BSize(wm) =
|
||||||
contentBoxBSize +
|
contentBoxBSize +
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm);
|
aReflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aStatus.IsComplete() &&
|
if (aStatus.IsComplete() &&
|
||||||
@ -792,24 +802,46 @@ void nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void nsFieldSetFrame::SetInitialChildList(ChildListID aListID,
|
void nsFieldSetFrame::SetInitialChildList(ChildListID aListID,
|
||||||
nsFrameList& aChildList) {
|
nsFrameList& aChildList) {
|
||||||
nsContainerFrame::SetInitialChildList(aListID, aChildList);
|
nsContainerFrame::SetInitialChildList(aListID, aChildList);
|
||||||
MOZ_ASSERT(aListID != kPrincipalList || GetInner(),
|
if (nsBlockFrame* legend = do_QueryFrame(GetLegend())) {
|
||||||
"Setting principal child list should populate our inner frame");
|
// 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,
|
void nsFieldSetFrame::AppendFrames(ChildListID aListID,
|
||||||
nsFrameList& aFrameList) {
|
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,
|
void nsFieldSetFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
|
||||||
const nsLineList::iterator* aPrevFrameLine,
|
const nsLineList::iterator* aPrevFrameLine,
|
||||||
nsFrameList& aFrameList) {
|
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) {
|
void nsFieldSetFrame::RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) {
|
||||||
MOZ_CRASH("nsFieldSetFrame::RemoveFrame not supported");
|
MOZ_CRASH("nsFieldSetFrame::RemoveFrame not supported");
|
||||||
}
|
}
|
||||||
@ -919,18 +951,16 @@ void nsFieldSetFrame::EnsureChildContinuation(nsIFrame* aChild,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aStatus.IsOverflowIncomplete()) {
|
if (aStatus.IsOverflowIncomplete()) {
|
||||||
if (nsFrameList* eoc =
|
if (nsFrameList* eoc = GetExcessOverflowContainers()) {
|
||||||
GetPropTableFrames(ExcessOverflowContainersProperty())) {
|
|
||||||
eoc->AppendFrames(nullptr, nifs);
|
eoc->AppendFrames(nullptr, nifs);
|
||||||
} else {
|
} else {
|
||||||
SetPropTableFrames(new (PresShell()) nsFrameList(nifs),
|
SetExcessOverflowContainers(std::move(nifs));
|
||||||
ExcessOverflowContainersProperty());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (nsFrameList* oc = GetOverflowFrames()) {
|
if (nsFrameList* oc = GetOverflowFrames()) {
|
||||||
oc->AppendFrames(nullptr, nifs);
|
oc->AppendFrames(nullptr, nifs);
|
||||||
} else {
|
} else {
|
||||||
SetOverflowFrames(nifs);
|
SetOverflowFrames(std::move(nifs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
|
|||||||
explicit nsFieldSetFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
|
explicit nsFieldSetFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
|
||||||
|
|
||||||
nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
|
nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
|
||||||
nsLayoutUtils::IntrinsicISizeType);
|
mozilla::IntrinsicISizeType);
|
||||||
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
||||||
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
||||||
|
|
||||||
@ -47,7 +47,6 @@ class nsFieldSetFrame final : public nsContainerFrame {
|
|||||||
gfxContext& aRenderingContext, nsPoint aPt,
|
gfxContext& aRenderingContext, nsPoint aPt,
|
||||||
const nsRect& aDirtyRect);
|
const nsRect& aDirtyRect);
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
virtual void SetInitialChildList(ChildListID aListID,
|
virtual void SetInitialChildList(ChildListID aListID,
|
||||||
nsFrameList& aChildList) override;
|
nsFrameList& aChildList) override;
|
||||||
virtual void AppendFrames(ChildListID aListID,
|
virtual void AppendFrames(ChildListID aListID,
|
||||||
@ -55,6 +54,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
|
|||||||
virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
|
virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
|
||||||
const nsLineList::iterator* aPrevFrameLine,
|
const nsLineList::iterator* aPrevFrameLine,
|
||||||
nsFrameList& aFrameList) override;
|
nsFrameList& aFrameList) override;
|
||||||
|
#ifdef DEBUG
|
||||||
virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
|
virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
|
|||||||
return nsContainerFrame::IsFrameOfType(
|
return nsContainerFrame::IsFrameOfType(
|
||||||
aFlags & ~nsIFrame::eCanContainOverflowContainers);
|
aFlags & ~nsIFrame::eCanContainOverflowContainers);
|
||||||
}
|
}
|
||||||
virtual nsIScrollableFrame* GetScrollTargetFrame() override {
|
virtual nsIScrollableFrame* GetScrollTargetFrame() const override {
|
||||||
return do_QueryFrame(GetInner());
|
return do_QueryFrame(GetInner());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ class nsFieldSetFrame final : public nsContainerFrame {
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult);
|
return MakeFrameName(u"FieldSet"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -90,9 +90,8 @@ class nsFieldSetFrame final : public nsContainerFrame {
|
|||||||
nsContainerFrame* GetInner() const;
|
nsContainerFrame* GetInner() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the frame that represents the legend if any. This may be
|
* Return the frame that represents the rendered legend if any.
|
||||||
* a nsLegendFrame or a nsHTMLScrollFrame with the nsLegendFrame as the
|
* https://html.spec.whatwg.org/multipage/rendering.html#rendered-legend
|
||||||
* scrolled frame (aka content insertion frame).
|
|
||||||
*/
|
*/
|
||||||
nsIFrame* GetLegend() const;
|
nsIFrame* GetLegend() const;
|
||||||
|
|
||||||
|
@ -164,10 +164,12 @@ void nsFileControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
labelBP +=
|
labelBP +=
|
||||||
lastLabelCont->GetLogicalUsedBorderAndPadding(wm).IStartEnd(wm);
|
lastLabelCont->GetLogicalUsedBorderAndPadding(wm).IStartEnd(wm);
|
||||||
}
|
}
|
||||||
auto* buttonFrame = mBrowseFilesOrDirs->GetPrimaryFrame();
|
nscoord availableISizeForLabel = contentISize;
|
||||||
nscoord availableISizeForLabel =
|
if (auto* buttonFrame = mBrowseFilesOrDirs->GetPrimaryFrame()) {
|
||||||
contentISize - buttonFrame->ISize(wm) -
|
availableISizeForLabel -=
|
||||||
buttonFrame->GetLogicalUsedMargin(wm).IStartEnd(wm);
|
buttonFrame->ISize(wm) +
|
||||||
|
buttonFrame->GetLogicalUsedMargin(wm).IStartEnd(wm);
|
||||||
|
}
|
||||||
if (CropTextToWidth(*aReflowInput.mRenderingContext, labelFrame,
|
if (CropTextToWidth(*aReflowInput.mRenderingContext, labelFrame,
|
||||||
availableISizeForLabel - labelBP, filename)) {
|
availableISizeForLabel - labelBP, filename)) {
|
||||||
nsBlockFrame::DidReflow(aPresContext, &aReflowInput);
|
nsBlockFrame::DidReflow(aPresContext, &aReflowInput);
|
||||||
@ -190,10 +192,8 @@ void nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
|||||||
|
|
||||||
// Remove the events.
|
// Remove the events.
|
||||||
if (mContent) {
|
if (mContent) {
|
||||||
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("drop"),
|
mContent->RemoveSystemEventListener(u"drop"_ns, mMouseListener, false);
|
||||||
mMouseListener, false);
|
mContent->RemoveSystemEventListener(u"dragover"_ns, mMouseListener, false);
|
||||||
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("dragover"),
|
|
||||||
mMouseListener, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aPostDestroyData.AddAnonymousContent(mTextContent.forget());
|
aPostDestroyData.AddAnonymousContent(mTextContent.forget());
|
||||||
@ -211,7 +211,7 @@ static already_AddRefed<Element> MakeAnonButton(Document* aDoc,
|
|||||||
// NOTE: SetIsNativeAnonymousRoot() has to be called before setting any
|
// NOTE: SetIsNativeAnonymousRoot() has to be called before setting any
|
||||||
// attribute.
|
// attribute.
|
||||||
button->SetIsNativeAnonymousRoot();
|
button->SetIsNativeAnonymousRoot();
|
||||||
button->SetPseudoElementType(PseudoStyleType::fileChooserButton);
|
button->SetPseudoElementType(PseudoStyleType::fileSelectorButton);
|
||||||
|
|
||||||
// Set the file picking button text depending on the current locale.
|
// Set the file picking button text depending on the current locale.
|
||||||
nsAutoString buttonTxt;
|
nsAutoString buttonTxt;
|
||||||
@ -282,10 +282,8 @@ nsresult nsFileControlFrame::CreateAnonymousContent(
|
|||||||
aElements.AppendElement(mTextContent);
|
aElements.AppendElement(mTextContent);
|
||||||
|
|
||||||
// We should be able to interact with the element by doing drag and drop.
|
// We should be able to interact with the element by doing drag and drop.
|
||||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("drop"), mMouseListener,
|
mContent->AddSystemEventListener(u"drop"_ns, mMouseListener, false);
|
||||||
false);
|
mContent->AddSystemEventListener(u"dragover"_ns, mMouseListener, false);
|
||||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("dragover"),
|
|
||||||
mMouseListener, false);
|
|
||||||
|
|
||||||
SyncDisabledState();
|
SyncDisabledState();
|
||||||
|
|
||||||
@ -368,7 +366,7 @@ nsFileControlFrame::DnDListener::HandleEvent(Event* aEvent) {
|
|||||||
bool supportsMultiple =
|
bool supportsMultiple =
|
||||||
inputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
|
inputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
|
||||||
if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) {
|
if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) {
|
||||||
dataTransfer->SetDropEffect(NS_LITERAL_STRING("none"));
|
dataTransfer->SetDropEffect(u"none"_ns);
|
||||||
aEvent->StopPropagation();
|
aEvent->StopPropagation();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -442,7 +440,7 @@ nsFileControlFrame::DnDListener::HandleEvent(Event* aEvent) {
|
|||||||
"Failed to dispatch input event");
|
"Failed to dispatch input event");
|
||||||
nsContentUtils::DispatchTrustedEvent(
|
nsContentUtils::DispatchTrustedEvent(
|
||||||
inputElement->OwnerDoc(), static_cast<nsINode*>(inputElement),
|
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() {
|
void nsFileControlFrame::SyncDisabledState() {
|
||||||
EventStates eventStates = mContent->AsElement()->State();
|
EventStates eventStates = mContent->AsElement()->State();
|
||||||
if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
|
if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
|
||||||
mBrowseFilesOrDirs->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
|
mBrowseFilesOrDirs->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, u""_ns,
|
||||||
EmptyString(), true);
|
true);
|
||||||
} else {
|
} else {
|
||||||
mBrowseFilesOrDirs->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true);
|
mBrowseFilesOrDirs->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true);
|
||||||
}
|
}
|
||||||
@ -572,7 +570,7 @@ void nsFileControlFrame::ContentStatesChanged(EventStates aStates) {
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult nsFileControlFrame::GetFrameName(nsAString& aResult) const {
|
nsresult nsFileControlFrame::GetFrameName(nsAString& aResult) const {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("FileControl"), aResult);
|
return MakeFrameName(u"FileControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ void nsGfxButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult nsGfxButtonControlFrame::GetFrameName(nsAString& aResult) const {
|
nsresult nsGfxButtonControlFrame::GetFrameName(nsAString& aResult) const {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("ButtonControl"), aResult);
|
return MakeFrameName(u"ButtonControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ nscoord nsHTMLButtonControlFrame::GetMinISize(gfxContext* aRenderingContext) {
|
|||||||
} else {
|
} else {
|
||||||
nsIFrame* kid = mFrames.FirstChild();
|
nsIFrame* kid = mFrames.FirstChild();
|
||||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
|
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
|
||||||
nsLayoutUtils::MIN_ISIZE);
|
IntrinsicISizeType::MinISize);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -143,8 +143,8 @@ nscoord nsHTMLButtonControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
|
|||||||
result = 0;
|
result = 0;
|
||||||
} else {
|
} else {
|
||||||
nsIFrame* kid = mFrames.FirstChild();
|
nsIFrame* kid = mFrames.FirstChild();
|
||||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
|
result = nsLayoutUtils::IntrinsicForContainer(
|
||||||
nsLayoutUtils::PREF_ISIZE);
|
aRenderingContext, kid, IntrinsicISizeType::PrefISize);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ void nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
// XXXbz Eventually we may want to check-and-bail if
|
// XXXbz Eventually we may want to check-and-bail if
|
||||||
// !aReflowInput.ShouldReflowAllKids() &&
|
// !aReflowInput.ShouldReflowAllKids() &&
|
||||||
// !NS_SUBTREE_DIRTY(firstKid).
|
// !firstKid->IsSubtreeDirty().
|
||||||
// We'd need to cache our ascent for that, of course.
|
// We'd need to cache our ascent for that, of course.
|
||||||
|
|
||||||
// Reflow the contents of the button.
|
// Reflow the contents of the button.
|
||||||
@ -206,7 +206,8 @@ void nsHTMLButtonControlFrame::ReflowButtonContents(
|
|||||||
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
||||||
|
|
||||||
// shorthand for a value we need to use in a bunch of places
|
// 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);
|
LogicalPoint childPos(wm);
|
||||||
childPos.I(wm) = clbp.IStart(wm);
|
childPos.I(wm) = clbp.IStart(wm);
|
||||||
|
@ -72,7 +72,7 @@ class nsHTMLButtonControlFrame : public nsContainerFrame,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("HTMLButtonControl"), aResult);
|
return MakeFrameName(u"HTMLButtonControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class nsImageControlFrame final : public nsImageFrame,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult GetFrameName(nsAString& aResult) const final {
|
nsresult GetFrameName(nsAString& aResult) const final {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("ImageControl"), aResult);
|
return MakeFrameName(u"ImageControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -138,7 +138,8 @@ nsresult nsImageControlFrame::HandleEvent(nsPresContext* aPresContext,
|
|||||||
mContent->GetProperty(nsGkAtoms::imageClickedPoint));
|
mContent->GetProperty(nsGkAtoms::imageClickedPoint));
|
||||||
if (lastClickPoint) {
|
if (lastClickPoint) {
|
||||||
// normally lastClickedPoint is not null, as it's allocated in Init()
|
// 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);
|
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);
|
mEventListener->SetFrame(nullptr);
|
||||||
|
|
||||||
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"),
|
mContent->RemoveSystemEventListener(u"keydown"_ns, mEventListener, false);
|
||||||
mEventListener, false);
|
mContent->RemoveSystemEventListener(u"keypress"_ns, mEventListener, false);
|
||||||
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("keypress"),
|
mContent->RemoveSystemEventListener(u"mousedown"_ns, mEventListener, false);
|
||||||
mEventListener, false);
|
mContent->RemoveSystemEventListener(u"mouseup"_ns, mEventListener, false);
|
||||||
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"),
|
mContent->RemoveSystemEventListener(u"mousemove"_ns, mEventListener, false);
|
||||||
mEventListener, false);
|
|
||||||
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mouseup"),
|
|
||||||
mEventListener, false);
|
|
||||||
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"),
|
|
||||||
mEventListener, false);
|
|
||||||
|
|
||||||
if (ShouldFireDropDownEvent()) {
|
if (ShouldFireDropDownEvent()) {
|
||||||
nsContentUtils::AddScriptRunner(
|
nsContentUtils::AddScriptRunner(
|
||||||
new AsyncEventDispatcher(mContent, NS_LITERAL_STRING("mozhidedropdown"),
|
new AsyncEventDispatcher(mContent, u"mozhidedropdown"_ns,
|
||||||
CanBubble::eYes, ChromeOnlyDispatch::eYes));
|
CanBubble::eYes, ChromeOnlyDispatch::eYes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,8 +394,8 @@ void nsListControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
bool autoBSize = (aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE);
|
bool autoBSize = (aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE);
|
||||||
|
|
||||||
mMightNeedSecondPass = autoBSize && (NS_SUBTREE_DIRTY(this) ||
|
mMightNeedSecondPass =
|
||||||
aReflowInput.ShouldReflowAllKids());
|
autoBSize && (IsSubtreeDirty() || aReflowInput.ShouldReflowAllKids());
|
||||||
|
|
||||||
ReflowInput state(aReflowInput);
|
ReflowInput state(aReflowInput);
|
||||||
int32_t length = GetNumberOfRows();
|
int32_t length = GetNumberOfRows();
|
||||||
@ -482,8 +477,7 @@ void nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext,
|
|||||||
MOZ_ASSERT(aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE,
|
MOZ_ASSERT(aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE,
|
||||||
"We should not have a computed block size here!");
|
"We should not have a computed block size here!");
|
||||||
|
|
||||||
mMightNeedSecondPass =
|
mMightNeedSecondPass = IsSubtreeDirty() || aReflowInput.ShouldReflowAllKids();
|
||||||
NS_SUBTREE_DIRTY(this) || aReflowInput.ShouldReflowAllKids();
|
|
||||||
|
|
||||||
WritingMode wm = aReflowInput.GetWritingMode();
|
WritingMode wm = aReflowInput.GetWritingMode();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -565,7 +559,7 @@ void nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext,
|
|||||||
mNumDisplayRows = 1;
|
mNumDisplayRows = 1;
|
||||||
mDropdownCanGrow = GetNumberOfRows() > 1;
|
mDropdownCanGrow = GetNumberOfRows() > 1;
|
||||||
} else {
|
} else {
|
||||||
nscoord bp = aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm);
|
nscoord bp = aReflowInput.ComputedLogicalBorderPadding(wm).BStartEnd(wm);
|
||||||
nscoord availableBSize = std::max(before, after) - bp;
|
nscoord availableBSize = std::max(before, after) - bp;
|
||||||
nscoord newBSize;
|
nscoord newBSize;
|
||||||
uint32_t rows;
|
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
|
// we need to hook up our listeners before the editor is initialized
|
||||||
mEventListener = new nsListEventListener(this);
|
mEventListener = new nsListEventListener(this);
|
||||||
|
|
||||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("keydown"), mEventListener,
|
mContent->AddSystemEventListener(u"keydown"_ns, mEventListener, false, false);
|
||||||
false, false);
|
mContent->AddSystemEventListener(u"keypress"_ns, mEventListener, false,
|
||||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("keypress"),
|
false);
|
||||||
mEventListener, false, false);
|
mContent->AddSystemEventListener(u"mousedown"_ns, mEventListener, false,
|
||||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("mousedown"),
|
false);
|
||||||
mEventListener, false, false);
|
mContent->AddSystemEventListener(u"mouseup"_ns, mEventListener, false, false);
|
||||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("mouseup"), mEventListener,
|
mContent->AddSystemEventListener(u"mousemove"_ns, mEventListener, false,
|
||||||
false, false);
|
false);
|
||||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("mousemove"),
|
|
||||||
mEventListener, false, false);
|
|
||||||
|
|
||||||
mStartSelectionIndex = kNothingSelected;
|
mStartSelectionIndex = kNothingSelected;
|
||||||
mEndSelectionIndex = kNothingSelected;
|
mEndSelectionIndex = kNothingSelected;
|
||||||
@ -1025,7 +1017,7 @@ void nsListControlFrame::SetComboboxFrame(nsIFrame* aComboboxFrame) {
|
|||||||
void nsListControlFrame::GetOptionText(uint32_t aIndex, nsAString& aStr) {
|
void nsListControlFrame::GetOptionText(uint32_t aIndex, nsAString& aStr) {
|
||||||
aStr.Truncate();
|
aStr.Truncate();
|
||||||
if (dom::HTMLOptionElement* optionElement = GetOption(aIndex)) {
|
if (dom::HTMLOptionElement* optionElement = GetOption(aIndex)) {
|
||||||
optionElement->GetText(aStr);
|
optionElement->GetRenderedLabel(aStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1290,8 +1282,8 @@ void nsListControlFrame::FireOnInputAndOnChange() {
|
|||||||
|
|
||||||
// Dispatch the change event.
|
// Dispatch the change event.
|
||||||
nsContentUtils::DispatchTrustedEvent(element->OwnerDoc(), element,
|
nsContentUtils::DispatchTrustedEvent(element->OwnerDoc(), element,
|
||||||
NS_LITERAL_STRING("change"),
|
u"change"_ns, CanBubble::eYes,
|
||||||
CanBubble::eYes, Cancelable::eNo);
|
Cancelable::eNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(void)
|
NS_IMETHODIMP_(void)
|
||||||
@ -1418,7 +1410,7 @@ void nsListControlFrame::DidReflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult nsListControlFrame::GetFrameName(nsAString& aResult) const {
|
nsresult nsListControlFrame::GetFrameName(nsAString& aResult) const {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("ListControl"), aResult);
|
return MakeFrameName(u"ListControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1602,7 +1594,7 @@ void nsListControlFrame::FireMenuItemActiveEvent() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FireDOMEvent(NS_LITERAL_STRING("DOMMenuItemActive"), optionContent);
|
FireDOMEvent(u"DOMMenuItemActive"_ns, optionContent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1641,11 +1633,10 @@ static bool FireShowDropDownEvent(nsIContent* aContent, bool aShow,
|
|||||||
if (ShouldFireDropDownEvent()) {
|
if (ShouldFireDropDownEvent()) {
|
||||||
nsString eventName;
|
nsString eventName;
|
||||||
if (aShow) {
|
if (aShow) {
|
||||||
eventName = aIsSourceTouchEvent
|
eventName = aIsSourceTouchEvent ? u"mozshowdropdown-sourcetouch"_ns
|
||||||
? NS_LITERAL_STRING("mozshowdropdown-sourcetouch")
|
: u"mozshowdropdown"_ns;
|
||||||
: NS_LITERAL_STRING("mozshowdropdown");
|
|
||||||
} else {
|
} else {
|
||||||
eventName = NS_LITERAL_STRING("mozhidedropdown");
|
eventName = u"mozhidedropdown"_ns;
|
||||||
}
|
}
|
||||||
nsContentUtils::DispatchChromeEvent(aContent->OwnerDoc(), aContent,
|
nsContentUtils::DispatchChromeEvent(aContent->OwnerDoc(), aContent,
|
||||||
eventName, CanBubble::eYes,
|
eventName, CanBubble::eYes,
|
||||||
@ -2275,11 +2266,11 @@ nsresult nsListControlFrame::KeyPress(dom::Event* aKeyEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsAutoString text;
|
nsAutoString text;
|
||||||
optionElement->GetText(text);
|
optionElement->GetRenderedLabel(text);
|
||||||
if (!StringBeginsWith(
|
if (!StringBeginsWith(
|
||||||
nsContentUtils::TrimWhitespace<
|
nsContentUtils::TrimWhitespace<
|
||||||
nsContentUtils::IsHTMLWhitespaceOrNBSP>(text, false),
|
nsContentUtils::IsHTMLWhitespaceOrNBSP>(text, false),
|
||||||
incrementalString, nsCaseInsensitiveStringComparator())) {
|
incrementalString, nsCaseInsensitiveStringComparator)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +97,8 @@ void nsMeterFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
ReflowBarFrame(barFrame, aPresContext, aReflowInput, aStatus);
|
ReflowBarFrame(barFrame, aPresContext, aReflowInput, aStatus);
|
||||||
|
|
||||||
aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
|
const auto wm = aReflowInput.GetWritingMode();
|
||||||
aReflowInput.ComputedSizeWithBorderPadding());
|
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
|
||||||
|
|
||||||
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||||
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
|
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
|
||||||
@ -185,7 +185,7 @@ nsresult nsMeterFrame::AttributeChanged(int32_t aNameSpaceID,
|
|||||||
LogicalSize nsMeterFrame::ComputeAutoSize(
|
LogicalSize nsMeterFrame::ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
||||||
nscoord aAvailableISize, const LogicalSize& aMargin,
|
nscoord aAvailableISize, const LogicalSize& aMargin,
|
||||||
const LogicalSize& aBorder, const LogicalSize& aPadding,
|
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
|
||||||
ComputeSizeFlags aFlags) {
|
ComputeSizeFlags aFlags) {
|
||||||
RefPtr<nsFontMetrics> fontMet =
|
RefPtr<nsFontMetrics> fontMet =
|
||||||
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
|
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
|
||||||
|
@ -33,7 +33,7 @@ class nsMeterFrame final : public nsContainerFrame,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("Meter"), aResult);
|
return MakeFrameName(u"Meter"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -49,8 +49,10 @@ class nsMeterFrame final : public nsContainerFrame,
|
|||||||
virtual mozilla::LogicalSize ComputeAutoSize(
|
virtual mozilla::LogicalSize ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
||||||
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
||||||
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
|
const mozilla::LogicalSize& aMargin,
|
||||||
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
|
const mozilla::LogicalSize& aBorderPadding,
|
||||||
|
const mozilla::StyleSizeOverrides& aSizeOverrides,
|
||||||
|
mozilla::ComputeSizeFlags aFlags) override;
|
||||||
|
|
||||||
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
||||||
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
||||||
|
@ -55,7 +55,7 @@ already_AddRefed<Element> nsNumberControlFrame::MakeAnonymousElement(
|
|||||||
if (aPseudoType == PseudoStyleType::mozNumberSpinDown ||
|
if (aPseudoType == PseudoStyleType::mozNumberSpinDown ||
|
||||||
aPseudoType == PseudoStyleType::mozNumberSpinUp) {
|
aPseudoType == PseudoStyleType::mozNumberSpinUp) {
|
||||||
resultElement->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_hidden,
|
resultElement->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_hidden,
|
||||||
NS_LITERAL_STRING("true"), false);
|
u"true"_ns, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aParent) {
|
if (aParent) {
|
||||||
@ -194,7 +194,7 @@ int32_t nsNumberControlFrame::GetSpinButtonForPointerEvent(
|
|||||||
// default UA style sheet. See the comment in forms.css for why.
|
// default UA style sheet. See the comment in forms.css for why.
|
||||||
LayoutDeviceIntPoint absPoint = aEvent->mRefPoint;
|
LayoutDeviceIntPoint absPoint = aEvent->mRefPoint;
|
||||||
nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
||||||
aEvent, absPoint, mSpinBox->GetPrimaryFrame());
|
aEvent, absPoint, RelativeTo{mSpinBox->GetPrimaryFrame()});
|
||||||
if (point != nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
|
if (point != nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
|
||||||
if (point.y < mSpinBox->GetPrimaryFrame()->GetSize().height / 2) {
|
if (point.y < mSpinBox->GetPrimaryFrame()->GetSize().height / 2) {
|
||||||
return eSpinButtonUp;
|
return eSpinButtonUp;
|
||||||
|
@ -60,7 +60,7 @@ class nsNumberControlFrame final : public nsTextControlFrame {
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult GetFrameName(nsAString& aResult) const override {
|
nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("NumberControl"), aResult);
|
return MakeFrameName(u"NumberControl"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -100,8 +100,8 @@ void nsProgressFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
nsCheckboxRadioFrame::RegUnRegAccessKey(this, true);
|
nsCheckboxRadioFrame::RegUnRegAccessKey(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
|
const auto wm = aReflowInput.GetWritingMode();
|
||||||
aReflowInput.ComputedSizeWithBorderPadding());
|
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
|
||||||
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||||
|
|
||||||
for (auto childFrame : PrincipalChildList()) {
|
for (auto childFrame : PrincipalChildList()) {
|
||||||
@ -202,7 +202,7 @@ nsresult nsProgressFrame::AttributeChanged(int32_t aNameSpaceID,
|
|||||||
LogicalSize nsProgressFrame::ComputeAutoSize(
|
LogicalSize nsProgressFrame::ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
||||||
nscoord aAvailableISize, const LogicalSize& aMargin,
|
nscoord aAvailableISize, const LogicalSize& aMargin,
|
||||||
const LogicalSize& aBorder, const LogicalSize& aPadding,
|
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
|
||||||
ComputeSizeFlags aFlags) {
|
ComputeSizeFlags aFlags) {
|
||||||
const WritingMode wm = GetWritingMode();
|
const WritingMode wm = GetWritingMode();
|
||||||
LogicalSize autoSize(wm);
|
LogicalSize autoSize(wm);
|
||||||
|
@ -38,7 +38,7 @@ class nsProgressFrame final : public nsContainerFrame,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("Progress"), aResult);
|
return MakeFrameName(u"Progress"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -54,8 +54,10 @@ class nsProgressFrame final : public nsContainerFrame,
|
|||||||
virtual mozilla::LogicalSize ComputeAutoSize(
|
virtual mozilla::LogicalSize ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
||||||
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
||||||
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
|
const mozilla::LogicalSize& aMargin,
|
||||||
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
|
const mozilla::LogicalSize& aBorderPadding,
|
||||||
|
const mozilla::StyleSizeOverrides& aSizeOverrides,
|
||||||
|
mozilla::ComputeSizeFlags aFlags) override;
|
||||||
|
|
||||||
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
||||||
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
||||||
|
@ -67,8 +67,7 @@ void nsRangeFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
|||||||
if (!mDummyTouchListener) {
|
if (!mDummyTouchListener) {
|
||||||
mDummyTouchListener = new DummyTouchListener();
|
mDummyTouchListener = new DummyTouchListener();
|
||||||
}
|
}
|
||||||
aContent->AddEventListener(NS_LITERAL_STRING("touchstart"),
|
aContent->AddEventListener(u"touchstart"_ns, mDummyTouchListener, false);
|
||||||
mDummyTouchListener, false);
|
|
||||||
|
|
||||||
return nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
|
return nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
|
||||||
}
|
}
|
||||||
@ -79,8 +78,7 @@ void nsRangeFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
|||||||
"nsRangeFrame should not have continuations; if it does we "
|
"nsRangeFrame should not have continuations; if it does we "
|
||||||
"need to call RegUnregAccessKey only for the first.");
|
"need to call RegUnregAccessKey only for the first.");
|
||||||
|
|
||||||
mContent->RemoveEventListener(NS_LITERAL_STRING("touchstart"),
|
mContent->RemoveEventListener(u"touchstart"_ns, mDummyTouchListener, false);
|
||||||
mDummyTouchListener, false);
|
|
||||||
|
|
||||||
nsCheckboxRadioFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
|
nsCheckboxRadioFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
|
||||||
aPostDestroyData.AddAnonymousContent(mTrackDiv.forget());
|
aPostDestroyData.AddAnonymousContent(mTrackDiv.forget());
|
||||||
@ -188,12 +186,10 @@ void nsRangeFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
if (computedBSize == NS_UNCONSTRAINEDSIZE) {
|
if (computedBSize == NS_UNCONSTRAINEDSIZE) {
|
||||||
computedBSize = 0;
|
computedBSize = 0;
|
||||||
}
|
}
|
||||||
|
const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(wm);
|
||||||
LogicalSize finalSize(
|
LogicalSize finalSize(
|
||||||
wm,
|
wm, aReflowInput.ComputedISize() + borderPadding.IStartEnd(wm),
|
||||||
aReflowInput.ComputedISize() +
|
computedBSize + borderPadding.BStartEnd(wm));
|
||||||
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm),
|
|
||||||
computedBSize +
|
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm));
|
|
||||||
aDesiredSize.SetSize(wm, finalSize);
|
aDesiredSize.SetSize(wm, finalSize);
|
||||||
|
|
||||||
ReflowAnonymousContent(aPresContext, aDesiredSize, aReflowInput);
|
ReflowAnonymousContent(aPresContext, aDesiredSize, aReflowInput);
|
||||||
@ -391,8 +387,8 @@ Decimal nsRangeFrame::GetValueAtEventPoint(WidgetGUIEvent* aEvent) {
|
|||||||
} else {
|
} else {
|
||||||
absPoint = aEvent->mRefPoint;
|
absPoint = aEvent->mRefPoint;
|
||||||
}
|
}
|
||||||
nsPoint point =
|
nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
|
||||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, absPoint, this);
|
aEvent, absPoint, RelativeTo{this});
|
||||||
|
|
||||||
if (point == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
|
if (point == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
|
||||||
// We don't want to change the current value for this error state.
|
// 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() {
|
void nsRangeFrame::UpdateForValueChange() {
|
||||||
if (NS_SUBTREE_DIRTY(this)) {
|
if (IsSubtreeDirty()) {
|
||||||
return; // we're going to be updated when we reflow
|
return; // we're going to be updated when we reflow
|
||||||
}
|
}
|
||||||
nsIFrame* rangeProgressFrame = mProgressDiv->GetPrimaryFrame();
|
nsIFrame* rangeProgressFrame = mProgressDiv->GetPrimaryFrame();
|
||||||
@ -628,7 +624,7 @@ nscoord nsRangeFrame::AutoCrossSize(nscoord aEm) {
|
|||||||
LogicalSize nsRangeFrame::ComputeAutoSize(
|
LogicalSize nsRangeFrame::ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
||||||
nscoord aAvailableISize, const LogicalSize& aMargin,
|
nscoord aAvailableISize, const LogicalSize& aMargin,
|
||||||
const LogicalSize& aBorder, const LogicalSize& aPadding,
|
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
|
||||||
ComputeSizeFlags aFlags) {
|
ComputeSizeFlags aFlags) {
|
||||||
bool isInlineOriented = IsInlineOriented();
|
bool isInlineOriented = IsInlineOriented();
|
||||||
auto em = StyleFont()->mFont.size * nsLayoutUtils::FontSizeInflationFor(this);
|
auto em = StyleFont()->mFont.size * nsLayoutUtils::FontSizeInflationFor(this);
|
||||||
|
@ -55,7 +55,7 @@ class nsRangeFrame final : public nsContainerFrame,
|
|||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||||
return MakeFrameName(NS_LITERAL_STRING("Range"), aResult);
|
return MakeFrameName(u"Range"_ns, aResult);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -72,11 +72,13 @@ class nsRangeFrame final : public nsContainerFrame,
|
|||||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||||
int32_t aModType) override;
|
int32_t aModType) override;
|
||||||
|
|
||||||
virtual mozilla::LogicalSize ComputeAutoSize(
|
mozilla::LogicalSize ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
||||||
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
||||||
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
|
const mozilla::LogicalSize& aMargin,
|
||||||
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
|
const mozilla::LogicalSize& aBorderPadding,
|
||||||
|
const mozilla::StyleSizeOverrides& aSizeOverrides,
|
||||||
|
mozilla::ComputeSizeFlags aFlags) override;
|
||||||
|
|
||||||
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
||||||
virtual nscoord GetPrefISize(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
|
// override bounds because the list item focus ring may extend outside
|
||||||
// the nsSelectsAreaFrame
|
// the nsSelectsAreaFrame
|
||||||
nsListControlFrame* listFrame = GetEnclosingListFrame(Frame());
|
nsListControlFrame* listFrame = GetEnclosingListFrame(Frame());
|
||||||
return listFrame->GetVisualOverflowRectRelativeToSelf() +
|
return listFrame->InkOverflowRectRelativeToSelf() +
|
||||||
listFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
listFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
||||||
}
|
}
|
||||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "nsFontMetrics.h"
|
#include "nsFontMetrics.h"
|
||||||
#include "nsTextControlFrame.h"
|
#include "nsTextControlFrame.h"
|
||||||
#include "nsIEditor.h"
|
#include "nsIEditor.h"
|
||||||
|
#include "nsIScrollableFrame.h"
|
||||||
#include "nsCaret.h"
|
#include "nsCaret.h"
|
||||||
#include "nsCSSPseudoElements.h"
|
#include "nsCSSPseudoElements.h"
|
||||||
#include "nsGenericHTMLElement.h"
|
#include "nsGenericHTMLElement.h"
|
||||||
@ -123,7 +124,7 @@ nsTextControlFrame::nsTextControlFrame(ComputedStyle* aStyle,
|
|||||||
|
|
||||||
nsTextControlFrame::~nsTextControlFrame() = default;
|
nsTextControlFrame::~nsTextControlFrame() = default;
|
||||||
|
|
||||||
nsIScrollableFrame* nsTextControlFrame::GetScrollTargetFrame() {
|
nsIScrollableFrame* nsTextControlFrame::GetScrollTargetFrame() const {
|
||||||
if (!mRootNode) {
|
if (!mRootNode) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -530,30 +531,32 @@ nscoord nsTextControlFrame::GetMinISize(gfxContext* aRenderingContext) {
|
|||||||
LogicalSize nsTextControlFrame::ComputeAutoSize(
|
LogicalSize nsTextControlFrame::ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
|
||||||
nscoord aAvailableISize, const LogicalSize& aMargin,
|
nscoord aAvailableISize, const LogicalSize& aMargin,
|
||||||
const LogicalSize& aBorder, const LogicalSize& aPadding,
|
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
|
||||||
ComputeSizeFlags aFlags) {
|
ComputeSizeFlags aFlags) {
|
||||||
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
|
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
|
||||||
LogicalSize autoSize = CalcIntrinsicSize(aRenderingContext, aWM, inflation);
|
LogicalSize autoSize = CalcIntrinsicSize(aRenderingContext, aWM, inflation);
|
||||||
|
|
||||||
// Note: nsContainerFrame::ComputeAutoSize only computes the inline-size (and
|
// Note: nsContainerFrame::ComputeAutoSize only computes the inline-size (and
|
||||||
// only for 'auto'), the block-size it returns is always NS_UNCONSTRAINEDSIZE.
|
// only for 'auto'), the block-size it returns is always NS_UNCONSTRAINEDSIZE.
|
||||||
const auto& iSizeCoord = StylePosition()->ISize(aWM);
|
const auto& styleISize = aSizeOverrides.mStyleISize
|
||||||
if (iSizeCoord.IsAuto()) {
|
? *aSizeOverrides.mStyleISize
|
||||||
if (aFlags & ComputeSizeFlags::eIClampMarginBoxMinSize) {
|
: StylePosition()->ISize(aWM);
|
||||||
|
if (styleISize.IsAuto()) {
|
||||||
|
if (aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize)) {
|
||||||
// CalcIntrinsicSize isn't aware of grid-item margin-box clamping, so we
|
// CalcIntrinsicSize isn't aware of grid-item margin-box clamping, so we
|
||||||
// fall back to nsContainerFrame's ComputeAutoSize to handle that.
|
// fall back to nsContainerFrame's ComputeAutoSize to handle that.
|
||||||
// XXX maybe a font-inflation issue here? (per the assertion below).
|
// XXX maybe a font-inflation issue here? (per the assertion below).
|
||||||
autoSize.ISize(aWM) =
|
autoSize.ISize(aWM) =
|
||||||
nsContainerFrame::ComputeAutoSize(aRenderingContext, aWM, aCBSize,
|
nsContainerFrame::ComputeAutoSize(
|
||||||
aAvailableISize, aMargin, aBorder,
|
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin,
|
||||||
aPadding, aFlags)
|
aBorderPadding, aSizeOverrides, aFlags)
|
||||||
.ISize(aWM);
|
.ISize(aWM);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
else {
|
else {
|
||||||
LogicalSize ancestorAutoSize = nsContainerFrame::ComputeAutoSize(
|
LogicalSize ancestorAutoSize = nsContainerFrame::ComputeAutoSize(
|
||||||
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin, aBorder,
|
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin,
|
||||||
aPadding, aFlags);
|
aBorderPadding, aSizeOverrides, aFlags);
|
||||||
// Disabled when there's inflation; see comment in GetXULPrefSize.
|
// Disabled when there's inflation; see comment in GetXULPrefSize.
|
||||||
MOZ_ASSERT(inflation != 1.0f ||
|
MOZ_ASSERT(inflation != 1.0f ||
|
||||||
ancestorAutoSize.ISize(aWM) == autoSize.ISize(aWM),
|
ancestorAutoSize.ISize(aWM) == autoSize.ISize(aWM),
|
||||||
@ -584,7 +587,7 @@ void nsTextControlFrame::ComputeBaseline(const ReflowInput& aReflowInput,
|
|||||||
nsLayoutUtils::GetFontMetricsForFrame(this, inflation);
|
nsLayoutUtils::GetFontMetricsForFrame(this, inflation);
|
||||||
mFirstBaseline = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight,
|
mFirstBaseline = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight,
|
||||||
wm.IsLineInverted()) +
|
wm.IsLineInverted()) +
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStart(wm);
|
aReflowInput.ComputedLogicalBorderPadding(wm).BStart(wm);
|
||||||
aDesiredSize.SetBlockStartAscent(mFirstBaseline);
|
aDesiredSize.SetBlockStartAscent(mFirstBaseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -604,13 +607,7 @@ void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
// set values of reflow's out parameters
|
// set values of reflow's out parameters
|
||||||
WritingMode wm = aReflowInput.GetWritingMode();
|
WritingMode wm = aReflowInput.GetWritingMode();
|
||||||
LogicalSize finalSize(
|
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
|
||||||
wm,
|
|
||||||
aReflowInput.ComputedISize() +
|
|
||||||
aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm),
|
|
||||||
aReflowInput.ComputedBSize() +
|
|
||||||
aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm));
|
|
||||||
aDesiredSize.SetSize(wm, finalSize);
|
|
||||||
|
|
||||||
ComputeBaseline(aReflowInput, aDesiredSize);
|
ComputeBaseline(aReflowInput, aDesiredSize);
|
||||||
|
|
||||||
@ -641,11 +638,11 @@ void nsTextControlFrame::ReflowTextControlChild(
|
|||||||
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
||||||
|
|
||||||
ReflowInput kidReflowInput(aPresContext, aReflowInput, aKid, availSize,
|
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
|
// Override padding with our computed padding in case we got it from theming
|
||||||
// or percentage.
|
// or percentage.
|
||||||
kidReflowInput.Init(aPresContext, Nothing(), nullptr,
|
kidReflowInput.Init(aPresContext, Nothing(), Nothing(),
|
||||||
&aReflowInput.ComputedPhysicalPadding());
|
Some(aReflowInput.ComputedLogicalPadding(wm)));
|
||||||
|
|
||||||
// Set computed width and computed height for the child
|
// Set computed width and computed height for the child
|
||||||
kidReflowInput.SetComputedWidth(aReflowInput.ComputedWidth());
|
kidReflowInput.SetComputedWidth(aReflowInput.ComputedWidth());
|
||||||
|
@ -57,10 +57,7 @@ class nsTextControlFrame : public nsContainerFrame,
|
|||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY void DestroyFrom(nsIFrame* aDestructRoot,
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY void DestroyFrom(nsIFrame* aDestructRoot,
|
||||||
PostDestroyData&) override;
|
PostDestroyData&) override;
|
||||||
|
|
||||||
nsIScrollableFrame* GetScrollTargetFrame() override;
|
nsIScrollableFrame* GetScrollTargetFrame() const override;
|
||||||
nsIScrollableFrame* GetScrollTargetFrame() const {
|
|
||||||
return const_cast<nsTextControlFrame*>(this)->GetScrollTargetFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
||||||
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
||||||
@ -68,8 +65,10 @@ class nsTextControlFrame : public nsContainerFrame,
|
|||||||
mozilla::LogicalSize ComputeAutoSize(
|
mozilla::LogicalSize ComputeAutoSize(
|
||||||
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
|
||||||
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
|
||||||
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
|
const mozilla::LogicalSize& aMargin,
|
||||||
const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
|
const mozilla::LogicalSize& aBorderPadding,
|
||||||
|
const mozilla::StyleSizeOverrides& aSizeOverrides,
|
||||||
|
mozilla::ComputeSizeFlags aFlags) override;
|
||||||
|
|
||||||
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
|
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
|
||||||
const ReflowInput& aReflowInput,
|
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. */
|
/* The aspect ratio of a box, in a "width / height" format. */
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/gfx/BaseSize.h"
|
||||||
#include "nsCoord.h"
|
#include "nsCoord.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
template <typename T>
|
||||||
|
struct ParamTraits;
|
||||||
|
} // namespace IPC
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
struct AspectRatio {
|
enum LogicalAxis : uint8_t;
|
||||||
AspectRatio() : mRatio(0.0f) {}
|
class LogicalSize;
|
||||||
explicit AspectRatio(float aRatio) : mRatio(std::max(aRatio, 0.0f)) {}
|
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) {
|
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();
|
||||||
}
|
}
|
||||||
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; }
|
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
|
// 0.0f in the division here (so that valid ratios always generate other
|
||||||
// valid ratios when inverted).
|
// valid ratios when inverted).
|
||||||
return AspectRatio(
|
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 {
|
bool operator==(const AspectRatio& aOther) const {
|
||||||
return mRatio == aOther.mRatio;
|
return mRatio == aOther.mRatio && mUseBoxSizing == aOther.mUseBoxSizing;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const AspectRatio& aOther) const {
|
bool operator!=(const AspectRatio& aOther) const {
|
||||||
@ -58,12 +126,16 @@ struct AspectRatio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const AspectRatio& aOther) const {
|
bool operator<(const AspectRatio& aOther) const {
|
||||||
|
MOZ_ASSERT(
|
||||||
|
mUseBoxSizing == aOther.mUseBoxSizing,
|
||||||
|
"Do not compare AspectRatio if their mUseBoxSizing are different.");
|
||||||
return mRatio < aOther.mRatio;
|
return mRatio < aOther.mRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 0.0f represents no aspect ratio.
|
// 0.0f represents no aspect ratio.
|
||||||
float mRatio;
|
float mRatio = 0.0f;
|
||||||
|
UseBoxSizing mUseBoxSizing = UseBoxSizing::No;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // 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