Bug 1900426 - Implement DnD for shadow-crossing selection r=jjaschke,smaug,dom-core
This patches allows 1. when the selection is shadow-crossing, dragging it will have the correct the drag image correctly displayed. It's hard to test, so no tests for this. 2. The selection can now be serialized and dropped. `test_drag_drop_shadow_crossing_selection.html` is the test for this. Differential Revision: https://phabricator.services.mozilla.com/D217318
This commit is contained in:
@@ -231,7 +231,6 @@ PresShell::CapturingContentInfo PresShell::sCapturingContentInfo;
|
||||
|
||||
// RangePaintInfo is used to paint ranges to offscreen buffers
|
||||
struct RangePaintInfo {
|
||||
RefPtr<nsRange> mRange;
|
||||
nsDisplayListBuilder mBuilder;
|
||||
nsDisplayList mList;
|
||||
|
||||
@@ -243,9 +242,8 @@ struct RangePaintInfo {
|
||||
// to paint them at this resolution.
|
||||
float mResolution = 1.0;
|
||||
|
||||
RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
|
||||
: mRange(aRange),
|
||||
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false),
|
||||
explicit RangePaintInfo(nsIFrame* aFrame)
|
||||
: mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false),
|
||||
mList(&mBuilder) {
|
||||
MOZ_COUNT_CTOR(RangePaintInfo);
|
||||
mBuilder.BeginFrame();
|
||||
@@ -4777,24 +4775,27 @@ nsRect PresShell::ClipListToRange(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* frame = i->Frame();
|
||||
nsIContent* content = frame->GetContent();
|
||||
if (content) {
|
||||
bool atStart = (content == aRange->GetStartContainer());
|
||||
bool atEnd = (content == aRange->GetEndContainer());
|
||||
bool atStart =
|
||||
content == aRange->GetMayCrossShadowBoundaryStartContainer();
|
||||
bool atEnd = content == aRange->GetMayCrossShadowBoundaryEndContainer();
|
||||
if ((atStart || atEnd) && frame->IsTextFrame()) {
|
||||
auto [frameStartOffset, frameEndOffset] = frame->GetOffsets();
|
||||
|
||||
int32_t hilightStart =
|
||||
atStart ? std::max(static_cast<int32_t>(aRange->StartOffset()),
|
||||
int32_t highlightStart =
|
||||
atStart ? std::max(static_cast<int32_t>(
|
||||
aRange->MayCrossShadowBoundaryStartOffset()),
|
||||
frameStartOffset)
|
||||
: frameStartOffset;
|
||||
int32_t hilightEnd =
|
||||
atEnd ? std::min(static_cast<int32_t>(aRange->EndOffset()),
|
||||
int32_t highlightEnd =
|
||||
atEnd ? std::min(static_cast<int32_t>(
|
||||
aRange->MayCrossShadowBoundaryEndOffset()),
|
||||
frameEndOffset)
|
||||
: frameEndOffset;
|
||||
if (hilightStart < hilightEnd) {
|
||||
if (highlightStart < highlightEnd) {
|
||||
// determine the location of the start and end edges of the range.
|
||||
nsPoint startPoint, endPoint;
|
||||
frame->GetPointFromOffset(hilightStart, &startPoint);
|
||||
frame->GetPointFromOffset(hilightEnd, &endPoint);
|
||||
frame->GetPointFromOffset(highlightStart, &startPoint);
|
||||
frame->GetPointFromOffset(highlightEnd, &endPoint);
|
||||
|
||||
// The clip rectangle is determined by taking the the start and
|
||||
// end points of the range, offset from the reference frame.
|
||||
@@ -4828,8 +4829,9 @@ nsRect PresShell::ClipListToRange(nsDisplayListBuilder* aBuilder,
|
||||
// Don't try to descend into subdocuments.
|
||||
// If this ever changes we'd need to add handling for subdocuments with
|
||||
// different zoom levels.
|
||||
else if (content->GetUncomposedDoc() ==
|
||||
aRange->GetStartContainer()->GetUncomposedDoc()) {
|
||||
else if (content->GetComposedDoc() ==
|
||||
aRange->GetMayCrossShadowBoundaryStartContainer()
|
||||
->GetComposedDoc()) {
|
||||
// if the node is within the range, append it to the temporary list
|
||||
bool before, after;
|
||||
nsresult rv =
|
||||
@@ -4874,14 +4876,18 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
|
||||
// If the start or end of the range is the document, just use the root
|
||||
// frame, otherwise get the common ancestor of the two endpoints of the
|
||||
// range.
|
||||
nsINode* startContainer = aRange->GetStartContainer();
|
||||
nsINode* endContainer = aRange->GetEndContainer();
|
||||
nsINode* startContainer = aRange->GetMayCrossShadowBoundaryStartContainer();
|
||||
nsINode* endContainer = aRange->GetMayCrossShadowBoundaryEndContainer();
|
||||
Document* doc = startContainer->GetComposedDoc();
|
||||
if (startContainer == doc || endContainer == doc) {
|
||||
ancestorFrame = rootFrame;
|
||||
} else {
|
||||
nsINode* ancestor = nsContentUtils::GetClosestCommonInclusiveAncestor(
|
||||
startContainer, endContainer);
|
||||
nsINode* ancestor =
|
||||
StaticPrefs::dom_shadowdom_selection_across_boundary_enabled()
|
||||
? nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(
|
||||
startContainer, endContainer)
|
||||
: nsContentUtils::GetClosestCommonInclusiveAncestor(startContainer,
|
||||
endContainer);
|
||||
NS_ASSERTION(!ancestor || ancestor->IsContent(),
|
||||
"common ancestor is not content");
|
||||
|
||||
@@ -4906,7 +4912,7 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
|
||||
}
|
||||
|
||||
// get a display list containing the range
|
||||
auto info = MakeUnique<RangePaintInfo>(aRange, ancestorFrame);
|
||||
auto info = MakeUnique<RangePaintInfo>(ancestorFrame);
|
||||
info->mBuilder.SetIncludeAllOutOfFlows();
|
||||
if (aForPrimarySelection) {
|
||||
info->mBuilder.SetSelectedFramesOnly();
|
||||
@@ -4914,7 +4920,9 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
|
||||
info->mBuilder.EnterPresShell(ancestorFrame);
|
||||
|
||||
ContentSubtreeIterator subtreeIter;
|
||||
nsresult rv = subtreeIter.Init(aRange);
|
||||
nsresult rv = StaticPrefs::dom_shadowdom_selection_across_boundary_enabled()
|
||||
? subtreeIter.InitWithAllowCrossShadowBoundary(aRange)
|
||||
: subtreeIter.Init(aRange);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user