зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1513658 - Implement DocumentOrShadowRoot.node(s)FromPoint. r=smaug
ChromeOnly for now, needs tests that I'll make sure to land with. Differential Revision: https://phabricator.services.mozilla.com/D14360 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
7fdb132838
Коммит
b0bc11783b
|
@ -330,6 +330,18 @@ void DocumentOrShadowRoot::ElementsFromPoint(
|
|||
aElements);
|
||||
}
|
||||
|
||||
void DocumentOrShadowRoot::NodesFromPoint(float aX, float aY,
|
||||
nsTArray<RefPtr<nsINode>>& aNodes) {
|
||||
QueryNodesFromPoint(*this, aX, aY, {}, FlushLayout::Yes, Multiple::Yes,
|
||||
aNodes);
|
||||
}
|
||||
|
||||
nsINode* DocumentOrShadowRoot::NodeFromPoint(float aX, float aY) {
|
||||
AutoTArray<RefPtr<nsINode>, 1> nodes;
|
||||
QueryNodesFromPoint(*this, aX, aY, {}, FlushLayout::Yes, Multiple::No, nodes);
|
||||
return nodes.SafeElementAt(0);
|
||||
}
|
||||
|
||||
Element* DocumentOrShadowRoot::ElementFromPointHelper(
|
||||
float aX, float aY, bool aIgnoreRootScrollFrame, bool aFlushLayout) {
|
||||
EnumSet<FrameForPointOption> options;
|
||||
|
|
|
@ -48,7 +48,7 @@ class DocumentOrShadowRoot {
|
|||
|
||||
public:
|
||||
explicit DocumentOrShadowRoot(nsIDocument&);
|
||||
explicit DocumentOrShadowRoot(mozilla::dom::ShadowRoot&);
|
||||
explicit DocumentOrShadowRoot(ShadowRoot&);
|
||||
|
||||
// Unusual argument naming is because of cycle collection macros.
|
||||
static void Traverse(DocumentOrShadowRoot* tmp,
|
||||
|
@ -103,8 +103,10 @@ class DocumentOrShadowRoot {
|
|||
Element* GetFullscreenElement();
|
||||
|
||||
Element* ElementFromPoint(float aX, float aY);
|
||||
void ElementsFromPoint(float aX, float aY,
|
||||
nsTArray<RefPtr<mozilla::dom::Element>>& aElements);
|
||||
nsINode* NodeFromPoint(float aX, float aY);
|
||||
|
||||
void ElementsFromPoint(float aX, float aY, nsTArray<RefPtr<Element>>&);
|
||||
void NodesFromPoint(float aX, float aY, nsTArray<RefPtr<nsINode>>&);
|
||||
|
||||
/**
|
||||
* Helper for elementFromPoint implementation that allows
|
||||
|
@ -214,8 +216,8 @@ class DocumentOrShadowRoot {
|
|||
*/
|
||||
Element* GetRetargetedFocusedElement();
|
||||
|
||||
nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheets;
|
||||
RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
|
||||
nsTArray<RefPtr<StyleSheet>> mStyleSheets;
|
||||
RefPtr<StyleSheetList> mDOMStyleSheets;
|
||||
|
||||
/*
|
||||
* mIdentifierMap works as follows for IDs:
|
||||
|
|
|
@ -75,6 +75,7 @@ skip-if = os == 'linux'
|
|||
tags = fullscreen
|
||||
# disabled on OS X for intermittent failures--bug-798848
|
||||
skip-if = toolkit == 'cocoa'
|
||||
[test_nodesFromPoint.html]
|
||||
[test_nodesFromRect.html]
|
||||
[test_parsingMode.html]
|
||||
[test_popup_blocker_chrome.xul]
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<style>
|
||||
div { text-align: justify; max-height: 100vh; }
|
||||
</style>
|
||||
<div id="testElement"></div>
|
||||
<script>
|
||||
|
||||
// TODO(emilio): Upstream to WPT once there's a spec for this and our
|
||||
// implementation is not [ChromeOnly].
|
||||
|
||||
const testElement = document.getElementById("testElement");
|
||||
|
||||
testElement.innerHTML = "X ".repeat(5000);
|
||||
|
||||
{
|
||||
const rect = testElement.getBoundingClientRect();
|
||||
|
||||
const node =
|
||||
document.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
is(node, testElement.firstChild, "Should return the text node");
|
||||
|
||||
const nodes =
|
||||
document.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
|
||||
const expected = [testElement.firstChild, testElement, document.body, document.documentElement];
|
||||
is(nodes.length, expected.length, "Not the amount of expected nodes");
|
||||
|
||||
for (let i = 0; i < nodes.length; ++i)
|
||||
is(nodes[i], expected[i]);
|
||||
}
|
||||
|
||||
// Make the test slotted, and add some fallback that we'll test later as well.
|
||||
{
|
||||
// Work around the sanitizer by building the DOM manually....
|
||||
const slot = document.createElement("slot");
|
||||
slot.innerHTML = "Y ".repeat(5000);
|
||||
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.appendChild(slot);
|
||||
|
||||
testElement.attachShadow({ mode: "open" }).appendChild(wrapper);
|
||||
}
|
||||
|
||||
{
|
||||
const rect = testElement.getBoundingClientRect();
|
||||
|
||||
const node =
|
||||
document.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
is(node, testElement.firstChild, "Should return the text node");
|
||||
|
||||
const nodes =
|
||||
document.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
|
||||
const expected = [testElement.firstChild, testElement, document.body, document.documentElement];
|
||||
is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes in the shadow?)");
|
||||
|
||||
for (let i = 0; i < nodes.length; ++i)
|
||||
is(nodes[i], expected[i]);
|
||||
}
|
||||
|
||||
{
|
||||
const rect = testElement.getBoundingClientRect();
|
||||
|
||||
const node =
|
||||
testElement.shadowRoot.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
is(node, testElement.shadowRoot.firstChild, "Should return the div wrapping the text node");
|
||||
|
||||
const nodes =
|
||||
testElement.shadowRoot.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
|
||||
const expected = [testElement.shadowRoot.firstChild];
|
||||
is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes outside of the shadow?)");
|
||||
|
||||
for (let i = 0; i < nodes.length; ++i)
|
||||
is(nodes[i], expected[i]);
|
||||
}
|
||||
|
||||
// Show the fallback.
|
||||
testElement.firstChild.remove();
|
||||
|
||||
{
|
||||
const rect = testElement.getBoundingClientRect();
|
||||
|
||||
const fallbackText = testElement.shadowRoot.querySelector("slot").firstChild;
|
||||
|
||||
const node =
|
||||
testElement.shadowRoot.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
is(node, fallbackText, "Should return the fallback text");
|
||||
|
||||
const nodes =
|
||||
testElement.shadowRoot.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
|
||||
const expected = [fallbackText, testElement.shadowRoot.firstChild];
|
||||
is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes outside of the shadow?)");
|
||||
|
||||
for (let i = 0; i < nodes.length; ++i)
|
||||
is(nodes[i], expected[i]);
|
||||
}
|
||||
|
||||
// Test the fallback from the document.
|
||||
{
|
||||
const rect = testElement.getBoundingClientRect();
|
||||
|
||||
const node =
|
||||
document.nodeFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
is(node, testElement, "Should return the element, since the fallback text is in the shadow");
|
||||
|
||||
const nodes =
|
||||
document.nodesFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||
|
||||
const expected = [testElement, document.body, document.documentElement];
|
||||
is(nodes.length, expected.length, "Not the amount of expected nodes (returned nodes inside of the shadow?)");
|
||||
|
||||
for (let i = 0; i < nodes.length; ++i)
|
||||
is(nodes[i], expected[i]);
|
||||
}
|
||||
</script>
|
|
@ -12,8 +12,16 @@
|
|||
interface DocumentOrShadowRoot {
|
||||
// Not implemented yet: bug 1430308.
|
||||
// Selection? getSelection();
|
||||
Element? elementFromPoint (float x, float y);
|
||||
sequence<Element> elementsFromPoint (float x, float y);
|
||||
Element? elementFromPoint(float x, float y);
|
||||
sequence<Element> elementsFromPoint(float x, float y);
|
||||
|
||||
// TODO: Avoid making these ChromeOnly, see:
|
||||
// https://github.com/w3c/csswg-drafts/issues/556
|
||||
[ChromeOnly]
|
||||
Node? nodeFromPoint(float x, float y);
|
||||
[ChromeOnly]
|
||||
sequence<Node> nodesFromPoint(float x, float y);
|
||||
|
||||
// Not implemented yet: bug 1430307.
|
||||
// CaretPosition? caretPositionFromPoint (float x, float y);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче