mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-31 11:37:30 +09:00
Issue #2135 - Bug 1430303: Implement ShadowRoot.pointerLockElement
This commit is contained in:
parent
c920f32df3
commit
3dfffeaeca
9 changed files with 138 additions and 29 deletions
|
|
@ -4,6 +4,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "DocumentOrShadowRoot.h"
|
#include "DocumentOrShadowRoot.h"
|
||||||
|
#include "mozilla/EventStateManager.h"
|
||||||
#include "mozilla/dom/StyleSheetList.h"
|
#include "mozilla/dom/StyleSheetList.h"
|
||||||
#include "nsDocument.h"
|
#include "nsDocument.h"
|
||||||
#include "nsFocusManager.h"
|
#include "nsFocusManager.h"
|
||||||
|
|
@ -144,5 +145,20 @@ DocumentOrShadowRoot::GetRetargetedFocusedElement()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Element*
|
||||||
|
DocumentOrShadowRoot::GetPointerLockElement()
|
||||||
|
{
|
||||||
|
nsCOMPtr<Element> pointerLockedElement =
|
||||||
|
do_QueryReferent(EventStateManager::sPointerLockedElement);
|
||||||
|
if (!pointerLockedElement) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIContent* retargetedPointerLockedElement = Retarget(pointerLockedElement);
|
||||||
|
return
|
||||||
|
retargetedPointerLockedElement && retargetedPointerLockedElement->IsElement() ?
|
||||||
|
retargetedPointerLockedElement->AsElement() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ public:
|
||||||
|
|
||||||
~DocumentOrShadowRoot() = default;
|
~DocumentOrShadowRoot() = default;
|
||||||
|
|
||||||
|
Element* GetPointerLockElement();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsIContent* Retarget(nsIContent* aContent) const;
|
nsIContent* Retarget(nsIContent* aContent) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11331,7 +11331,7 @@ GetPointerLockError(Element* aElement, Element* aCurrentLock,
|
||||||
return "PointerLockDeniedInUse";
|
return "PointerLockDeniedInUse";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aElement->IsInUncomposedDoc()) {
|
if (!aElement->IsInComposedDoc()) {
|
||||||
return "PointerLockDeniedNotInDocument";
|
return "PointerLockDeniedNotInDocument";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -11382,11 +11382,11 @@ ChangePointerLockedElement(Element* aElement, nsIDocument* aDocument,
|
||||||
MOZ_ASSERT(aDocument);
|
MOZ_ASSERT(aDocument);
|
||||||
MOZ_ASSERT(aElement != aPointerLockedElement);
|
MOZ_ASSERT(aElement != aPointerLockedElement);
|
||||||
if (aPointerLockedElement) {
|
if (aPointerLockedElement) {
|
||||||
MOZ_ASSERT(aPointerLockedElement->GetUncomposedDoc() == aDocument);
|
MOZ_ASSERT(aPointerLockedElement->GetComposedDoc() == aDocument);
|
||||||
aPointerLockedElement->ClearPointerLock();
|
aPointerLockedElement->ClearPointerLock();
|
||||||
}
|
}
|
||||||
if (aElement) {
|
if (aElement) {
|
||||||
MOZ_ASSERT(aElement->GetUncomposedDoc() == aDocument);
|
MOZ_ASSERT(aElement->GetComposedDoc() == aDocument);
|
||||||
aElement->SetPointerLock();
|
aElement->SetPointerLock();
|
||||||
EventStateManager::sPointerLockedElement = do_GetWeakReference(aElement);
|
EventStateManager::sPointerLockedElement = do_GetWeakReference(aElement);
|
||||||
EventStateManager::sPointerLockedDoc = do_GetWeakReference(aDocument);
|
EventStateManager::sPointerLockedDoc = do_GetWeakReference(aDocument);
|
||||||
|
|
@ -11410,9 +11410,9 @@ PointerLockRequest::Run()
|
||||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||||
nsDocument* d = static_cast<nsDocument*>(doc.get());
|
nsDocument* d = static_cast<nsDocument*>(doc.get());
|
||||||
const char* error = nullptr;
|
const char* error = nullptr;
|
||||||
if (!e || !d || !e->GetUncomposedDoc()) {
|
if (!e || !d || !e->GetComposedDoc()) {
|
||||||
error = "PointerLockDeniedNotInDocument";
|
error = "PointerLockDeniedNotInDocument";
|
||||||
} else if (e->GetUncomposedDoc() != d) {
|
} else if (e->GetComposedDoc() != d) {
|
||||||
error = "PointerLockDeniedMovedDocument";
|
error = "PointerLockDeniedMovedDocument";
|
||||||
}
|
}
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
|
@ -11578,25 +11578,6 @@ nsDocument::GetMozPointerLockElement(nsIDOMElement** aPointerLockedElement)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Element*
|
|
||||||
nsIDocument::GetPointerLockElement()
|
|
||||||
{
|
|
||||||
nsCOMPtr<Element> pointerLockedElement =
|
|
||||||
do_QueryReferent(EventStateManager::sPointerLockedElement);
|
|
||||||
if (!pointerLockedElement) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure pointer locked element is in the same document.
|
|
||||||
nsCOMPtr<nsIDocument> pointerLockedDoc =
|
|
||||||
do_QueryReferent(EventStateManager::sPointerLockedDoc);
|
|
||||||
if (pointerLockedDoc != this) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointerLockedElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsDocument::Observe(nsISupports *aSubject,
|
nsDocument::Observe(nsISupports *aSubject,
|
||||||
const char *aTopic,
|
const char *aTopic,
|
||||||
|
|
|
||||||
|
|
@ -2643,7 +2643,6 @@ public:
|
||||||
return !!GetFullscreenElement();
|
return !!GetFullscreenElement();
|
||||||
}
|
}
|
||||||
void ExitFullscreen();
|
void ExitFullscreen();
|
||||||
Element* GetPointerLockElement();
|
|
||||||
void ExitPointerLock()
|
void ExitPointerLock()
|
||||||
{
|
{
|
||||||
UnlockPointer(this);
|
UnlockPointer(this);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--https://bugzilla.mozilla.org/show_bug.cgi?id=633602-->
|
||||||
|
<head>
|
||||||
|
<title>Bug 633602</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js">
|
||||||
|
</script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js">
|
||||||
|
</script>
|
||||||
|
<script type="application/javascript" src="pointerlock_utils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank"
|
||||||
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=633602">
|
||||||
|
Mozilla Bug 633602
|
||||||
|
</a>
|
||||||
|
<div id="host"></div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="text/javascript">
|
||||||
|
/*
|
||||||
|
* Test for Bug 1430303
|
||||||
|
* Make sure DOM API is correct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
var div,
|
||||||
|
host,
|
||||||
|
hasRequestPointerLock = false,
|
||||||
|
pointerLockChangeEventFired = false,
|
||||||
|
pointerUnlocked = false,
|
||||||
|
pointerLocked = false,
|
||||||
|
hasExitPointerLock = false,
|
||||||
|
pointerLockElement = false,
|
||||||
|
hasMovementX = false,
|
||||||
|
hasMovementY = false;
|
||||||
|
gotContextMenuEvent = false;
|
||||||
|
|
||||||
|
function runTests () {
|
||||||
|
ok(hasRequestPointerLock, "Element should have requestPointerLock.");
|
||||||
|
ok(pointerLockChangeEventFired, "pointerlockchange event should fire.");
|
||||||
|
ok(pointerUnlocked, "Should be able to unlock pointer locked element.");
|
||||||
|
ok(pointerLocked, "Requested element should be able to lock.");
|
||||||
|
ok(hasExitPointerLock, "Document should have exitPointerLock");
|
||||||
|
ok(pointerLockElement, "Document should keep track of correct pointer locked element");
|
||||||
|
ok(hasMovementX, "Mouse Event should have movementX.");
|
||||||
|
ok(hasMovementY, "Mouse Event should have movementY.");
|
||||||
|
ok(!gotContextMenuEvent, "Shouldn't have got a contextmenu event.");
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseMoveHandler(e) {
|
||||||
|
info("Got mousemove");
|
||||||
|
document.removeEventListener("mousemove", mouseMoveHandler);
|
||||||
|
|
||||||
|
hasMovementX = "movementX" in e;
|
||||||
|
hasMovementY = "movementY" in e;
|
||||||
|
|
||||||
|
hasExitPointerLock = "exitPointerLock" in document;
|
||||||
|
document.exitPointerLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("pointerlockchange", function (e) {
|
||||||
|
pointerLockChangeEventFired = true;
|
||||||
|
|
||||||
|
if (document.pointerLockElement) {
|
||||||
|
info("Got pointerlockchange for entering");
|
||||||
|
pointerLocked = true;
|
||||||
|
pointerLockElement = document.pointerLockElement === host;
|
||||||
|
is(host.shadowRoot.firstChild, host.shadowRoot.pointerLockElement,
|
||||||
|
"ShadowRoot's pointerLockElement shouldn't be retargeted.");
|
||||||
|
|
||||||
|
window.addEventListener("contextmenu",
|
||||||
|
function() { gotContextMenuEvent = true; },
|
||||||
|
true);
|
||||||
|
synthesizeMouse(document.body, 4, 4,
|
||||||
|
{ type: "contextmenu", button: 2 },
|
||||||
|
window);
|
||||||
|
|
||||||
|
document.addEventListener("mousemove", mouseMoveHandler);
|
||||||
|
synthesizeMouseAtCenter(host, {type: "mousemove"}, window);
|
||||||
|
} else {
|
||||||
|
info("Got pointerlockchange for exiting");
|
||||||
|
pointerUnlocked = true;
|
||||||
|
addFullscreenChangeContinuation("exit", function() {
|
||||||
|
info("Got fullscreenchange for exiting");
|
||||||
|
runTests();
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
document.exitFullscreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
host = document.getElementById("host");
|
||||||
|
var sr = host.attachShadow({mode: "open"});
|
||||||
|
sr.innerHTML = "<div><div>";
|
||||||
|
div = sr.firstChild;
|
||||||
|
info("Requesting fullscreen on parent");
|
||||||
|
addFullscreenChangeContinuation("enter", function() {
|
||||||
|
info("Got fullscreenchange for entering");
|
||||||
|
hasRequestPointerLock = "requestPointerLock" in div;
|
||||||
|
div.requestPointerLock();
|
||||||
|
});
|
||||||
|
host.requestFullscreen();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -8,6 +8,7 @@ tags = fullscreen
|
||||||
support-files =
|
support-files =
|
||||||
pointerlock_utils.js
|
pointerlock_utils.js
|
||||||
file_pointerlock-api.html
|
file_pointerlock-api.html
|
||||||
|
file_pointerlock-api-with-shadow.html
|
||||||
file_pointerlockerror.html
|
file_pointerlockerror.html
|
||||||
file_escapeKey.html
|
file_escapeKey.html
|
||||||
file_withoutDOM.html
|
file_withoutDOM.html
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
|
||||||
["full-screen-api.unprefix.enabled", true],
|
["full-screen-api.unprefix.enabled", true],
|
||||||
["full-screen-api.allow-trusted-requests-only", false],
|
["full-screen-api.allow-trusted-requests-only", false],
|
||||||
["full-screen-api.transition-duration.enter", "0 0"],
|
["full-screen-api.transition-duration.enter", "0 0"],
|
||||||
["full-screen-api.transition-duration.leave", "0 0"]
|
["full-screen-api.transition-duration.leave", "0 0"],
|
||||||
|
["dom.webcomponents.enabled", true]
|
||||||
]}, nextTest);
|
]}, nextTest);
|
||||||
|
|
||||||
// Run the tests which go full-screen in new window, as Mochitests
|
// Run the tests which go full-screen in new window, as Mochitests
|
||||||
|
|
@ -49,6 +50,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
|
||||||
"file_movementXY.html",
|
"file_movementXY.html",
|
||||||
"file_nestedFullScreen.html",
|
"file_nestedFullScreen.html",
|
||||||
"file_pointerlock-api.html",
|
"file_pointerlock-api.html",
|
||||||
|
"file_pointerlock-api-with-shadow.html",
|
||||||
"file_pointerlockerror.html",
|
"file_pointerlockerror.html",
|
||||||
"file_pointerLockPref.html",
|
"file_pointerLockPref.html",
|
||||||
"file_removedFromDOM.html",
|
"file_removedFromDOM.html",
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,6 @@ partial interface Document {
|
||||||
// https://w3c.github.io/pointerlock/#extensions-to-the-document-interface
|
// https://w3c.github.io/pointerlock/#extensions-to-the-document-interface
|
||||||
// https://w3c.github.io/pointerlock/#extensions-to-the-documentorshadowroot-mixin
|
// https://w3c.github.io/pointerlock/#extensions-to-the-documentorshadowroot-mixin
|
||||||
partial interface Document {
|
partial interface Document {
|
||||||
readonly attribute Element? pointerLockElement;
|
|
||||||
[BinaryName="pointerLockElement", Pref="pointer-lock-api.prefixed.enabled"]
|
[BinaryName="pointerLockElement", Pref="pointer-lock-api.prefixed.enabled"]
|
||||||
readonly attribute Element? mozPointerLockElement;
|
readonly attribute Element? mozPointerLockElement;
|
||||||
void exitPointerLock();
|
void exitPointerLock();
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@ interface DocumentOrShadowRoot {
|
||||||
readonly attribute Element? activeElement;
|
readonly attribute Element? activeElement;
|
||||||
readonly attribute StyleSheetList styleSheets;
|
readonly attribute StyleSheetList styleSheets;
|
||||||
|
|
||||||
// Not implemented yet: bug 1430303.
|
readonly attribute Element? pointerLockElement;
|
||||||
// readonly attribute Element? pointerLockElement;
|
|
||||||
// Not implemented yet: bug 1430305.
|
// Not implemented yet: bug 1430305.
|
||||||
// readonly attribute Element? fullscreenElement;
|
// readonly attribute Element? fullscreenElement;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue