Commit 575ba7c7 authored by scheib@chromium.org's avatar scheib@chromium.org

webkitPointerLockElement returns null when pointer lock request is pending.

https://bugs.webkit.org/show_bug.cgi?id=91186

Reviewed by Dimitri Glazkov.

Source/WebCore:

Script should wait for a pointerlockchange event before detecting
if it has acquired lock. However, if a script attempted to poll
pointerLockElement it could be confused when lock was still pending.
This change ensures that if lock is not yet acquired then
pointerLockElement will return null.

Test: pointer-lock/pointerlockelement-null-when-pending.html

* dom/Document.cpp:
(WebCore::Document::webkitPointerLockElement):
* page/PointerLockController.cpp:
(WebCore::PointerLockController::requestPointerLock):
(WebCore::PointerLockController::elementRemoved):
(WebCore::PointerLockController::documentDetached):
(WebCore::PointerLockController::lockPending):
(WebCore):
(WebCore::PointerLockController::didAcquirePointerLock):
(WebCore::PointerLockController::didNotAcquirePointerLock):
(WebCore::PointerLockController::didLosePointerLock):
(WebCore::PointerLockController::clearElement):
* page/PointerLockController.h:
(PointerLockController):

LayoutTests:

* pointer-lock/locked-element-iframe-removed-from-dom-expected.txt:
* pointer-lock/locked-element-iframe-removed-from-dom.html:
     Updated to reflect new behavior of null returned when lock is pending.
* pointer-lock/pointerlockelement-null-when-pending-expected.txt: Added.
* pointer-lock/pointerlockelement-null-when-pending.html: Added.
     New test specifically for testing null return when lock is pending.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@127606 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a5337aa0
2012-09-05 Vincent Scheib <scheib@chromium.org>
webkitPointerLockElement returns null when pointer lock request is pending.
https://bugs.webkit.org/show_bug.cgi?id=91186
Reviewed by Dimitri Glazkov.
* pointer-lock/locked-element-iframe-removed-from-dom-expected.txt:
* pointer-lock/locked-element-iframe-removed-from-dom.html:
Updated to reflect new behavior of null returned when lock is pending.
* pointer-lock/pointerlockelement-null-when-pending-expected.txt: Added.
* pointer-lock/pointerlockelement-null-when-pending.html: Added.
New test specifically for testing null return when lock is pending.
2012-09-05 Christophe Dumez <christophe.dumez@intel.com> 2012-09-05 Christophe Dumez <christophe.dumez@intel.com>
[EFL][WK2] Provide implementation for TestRunner::pathToLocalResource() [EFL][WK2] Provide implementation for TestRunner::pathToLocalResource()
...@@ -10,7 +10,7 @@ PASS targetIframe1.contentDocument.webkitPointerLockElement is targetDiv1 ...@@ -10,7 +10,7 @@ PASS targetIframe1.contentDocument.webkitPointerLockElement is targetDiv1
PASS targetDiv1.parentElement.parentElement is targetIframe1.contentDocument.body PASS targetDiv1.parentElement.parentElement is targetIframe1.contentDocument.body
Remove iframe & immediately lock target2. (main document handler) Remove iframe & immediately lock target2. (main document handler)
Remove iframe & immediately lock target2. (iframe handler) Remove iframe & immediately lock target2. (iframe handler)
PASS document.webkitPointerLockElement is targetDiv2 PASS document.webkitPointerLockElement is null
PASS onwebkitpointerlockchange received after: Remove iframe & immediately lock target2. (main document handler) PASS onwebkitpointerlockchange received after: Remove iframe & immediately lock target2. (main document handler)
PASS successfullyParsed is true PASS successfullyParsed is true
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
expectNoEvents("Remove iframe & immediately lock target2. (iframe handler)", targetIframe1.contentDocument); expectNoEvents("Remove iframe & immediately lock target2. (iframe handler)", targetIframe1.contentDocument);
targetIframe1.parentElement.removeChild(targetIframe1); targetIframe1.parentElement.removeChild(targetIframe1);
targetDiv2.webkitRequestPointerLock(); targetDiv2.webkitRequestPointerLock();
shouldBe("document.webkitPointerLockElement", "targetDiv2"); shouldBe("document.webkitPointerLockElement", "null");
// doNextStep called by event handler. // doNextStep called by event handler.
}, },
]; ];
......
Test pointerLockElement is null when a lock is pending.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS document.webkitPointerLockElement is null
Lock.
PASS document.webkitPointerLockElement is null
PASS onwebkitpointerlockchange received after: Lock.
PASS document.webkitPointerLockElement is targetDiv1
Unlock.
PASS document.webkitPointerLockElement is targetDiv1
PASS onwebkitpointerlockchange received after: Unlock.
PASS document.webkitPointerLockElement is null
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML>
<html>
<head>
<script src="../http/tests/resources/js-test-pre.js"></script>
<script src="../http/tests/resources/pointer-lock/pointer-lock-test-harness.js"></script>
</head>
<body>
<div>
<div id="target1"></div>
</div>
<script>
description("Test pointerLockElement is null when a lock is pending.")
window.jsTestIsAsync = true;
targetDiv1 = document.getElementById("target1");
todo = [
function () {
shouldBe("document.webkitPointerLockElement", "null");
testRunner.setPointerLockWillRespondAsynchronously();
expectOnlyChangeEvent("Lock.");
targetDiv1.webkitRequestPointerLock();
doNextStep();
},
function () {
shouldBe("document.webkitPointerLockElement", "null");
testRunner.didAcquirePointerLock();
// doNextStep called from event handler set with expect...
},
function () {
shouldBe("document.webkitPointerLockElement", "targetDiv1");
expectOnlyChangeEvent("Unlock.");
document.webkitExitPointerLock();
shouldBe("document.webkitPointerLockElement", "targetDiv1");
// doNextStep called from event handler set with expect...
},
function () {
shouldBe("document.webkitPointerLockElement", "null");
doNextStep();
},
];
doNextStep();
</script>
<script src="../http/tests/resources/js-test-post.js"></script>
</body>
</html>
2012-09-05 Vincent Scheib <scheib@chromium.org>
webkitPointerLockElement returns null when pointer lock request is pending.
https://bugs.webkit.org/show_bug.cgi?id=91186
Reviewed by Dimitri Glazkov.
Script should wait for a pointerlockchange event before detecting
if it has acquired lock. However, if a script attempted to poll
pointerLockElement it could be confused when lock was still pending.
This change ensures that if lock is not yet acquired then
pointerLockElement will return null.
Test: pointer-lock/pointerlockelement-null-when-pending.html
* dom/Document.cpp:
(WebCore::Document::webkitPointerLockElement):
* page/PointerLockController.cpp:
(WebCore::PointerLockController::requestPointerLock):
(WebCore::PointerLockController::elementRemoved):
(WebCore::PointerLockController::documentDetached):
(WebCore::PointerLockController::lockPending):
(WebCore):
(WebCore::PointerLockController::didAcquirePointerLock):
(WebCore::PointerLockController::didNotAcquirePointerLock):
(WebCore::PointerLockController::didLosePointerLock):
(WebCore::PointerLockController::clearElement):
* page/PointerLockController.h:
(PointerLockController):
2012-09-05 Sami Kyostila <skyostil@chromium.org> 2012-09-05 Sami Kyostila <skyostil@chromium.org>
[chromium] Wire up scrollable sublayers in ScrollingCoordinatorChromium [chromium] Wire up scrollable sublayers in ScrollingCoordinatorChromium
...@@ -5872,7 +5872,7 @@ void Document::webkitExitPointerLock() ...@@ -5872,7 +5872,7 @@ void Document::webkitExitPointerLock()
Element* Document::webkitPointerLockElement() const Element* Document::webkitPointerLockElement() const
{ {
if (!page()) if (!page() || page()->pointerLockController()->lockPending())
return 0; return 0;
if (Element* element = page()->pointerLockController()->element()) { if (Element* element = page()->pointerLockController()->element()) {
if (element->document() == this) if (element->document() == this)
......
...@@ -62,6 +62,7 @@ void PointerLockController::requestPointerLock(Element* target) ...@@ -62,6 +62,7 @@ void PointerLockController::requestPointerLock(Element* target)
enqueueEvent(eventNames().webkitpointerlockchangeEvent, target); enqueueEvent(eventNames().webkitpointerlockchangeEvent, target);
m_element = target; m_element = target;
} else if (m_page->chrome()->client()->requestPointerLock()) { } else if (m_page->chrome()->client()->requestPointerLock()) {
m_lockPending = true;
m_element = target; m_element = target;
} else { } else {
enqueueEvent(eventNames().webkitpointerlockerrorEvent, target); enqueueEvent(eventNames().webkitpointerlockerrorEvent, target);
...@@ -79,7 +80,7 @@ void PointerLockController::elementRemoved(Element* element) ...@@ -79,7 +80,7 @@ void PointerLockController::elementRemoved(Element* element)
m_documentOfRemovedElementWhileWaitingForUnlock = m_element->document(); m_documentOfRemovedElementWhileWaitingForUnlock = m_element->document();
// Set element null immediately to block any future interaction with it // Set element null immediately to block any future interaction with it
// including mouse events received before the unlock completes. // including mouse events received before the unlock completes.
m_element = 0; clearElement();
requestPointerUnlock(); requestPointerUnlock();
} }
} }
...@@ -87,11 +88,16 @@ void PointerLockController::elementRemoved(Element* element) ...@@ -87,11 +88,16 @@ void PointerLockController::elementRemoved(Element* element)
void PointerLockController::documentDetached(Document* document) void PointerLockController::documentDetached(Document* document)
{ {
if (m_element && m_element->document() == document) { if (m_element && m_element->document() == document) {
m_element = 0; clearElement();
requestPointerUnlock(); requestPointerUnlock();
} }
} }
bool PointerLockController::lockPending() const
{
return m_lockPending;
}
Element* PointerLockController::element() const Element* PointerLockController::element() const
{ {
return m_element.get(); return m_element.get();
...@@ -100,18 +106,19 @@ Element* PointerLockController::element() const ...@@ -100,18 +106,19 @@ Element* PointerLockController::element() const
void PointerLockController::didAcquirePointerLock() void PointerLockController::didAcquirePointerLock()
{ {
enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element.get()); enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element.get());
m_lockPending = false;
} }
void PointerLockController::didNotAcquirePointerLock() void PointerLockController::didNotAcquirePointerLock()
{ {
enqueueEvent(eventNames().webkitpointerlockerrorEvent, m_element.get()); enqueueEvent(eventNames().webkitpointerlockerrorEvent, m_element.get());
m_element = 0; clearElement();
} }
void PointerLockController::didLosePointerLock() void PointerLockController::didLosePointerLock()
{ {
enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element ? m_element->document() : m_documentOfRemovedElementWhileWaitingForUnlock.get()); enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element ? m_element->document() : m_documentOfRemovedElementWhileWaitingForUnlock.get());
m_element = 0; clearElement();
m_documentOfRemovedElementWhileWaitingForUnlock = 0; m_documentOfRemovedElementWhileWaitingForUnlock = 0;
} }
...@@ -127,6 +134,12 @@ void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& e ...@@ -127,6 +134,12 @@ void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& e
m_element->dispatchMouseEvent(event, eventNames().clickEvent, event.clickCount()); m_element->dispatchMouseEvent(event, eventNames().clickEvent, event.clickCount());
} }
void PointerLockController::clearElement()
{
m_lockPending = false;
m_element = 0;
}
void PointerLockController::enqueueEvent(const AtomicString& type, Element* element) void PointerLockController::enqueueEvent(const AtomicString& type, Element* element)
{ {
if (element) if (element)
......
...@@ -48,6 +48,7 @@ public: ...@@ -48,6 +48,7 @@ public:
void requestPointerUnlock(); void requestPointerUnlock();
void elementRemoved(Element*); void elementRemoved(Element*);
void documentDetached(Document*); void documentDetached(Document*);
bool lockPending() const;
Element* element() const; Element* element() const;
void didAcquirePointerLock(); void didAcquirePointerLock();
...@@ -57,9 +58,11 @@ public: ...@@ -57,9 +58,11 @@ public:
private: private:
explicit PointerLockController(Page*); explicit PointerLockController(Page*);
void clearElement();
void enqueueEvent(const AtomicString& type, Element*); void enqueueEvent(const AtomicString& type, Element*);
void enqueueEvent(const AtomicString& type, Document*); void enqueueEvent(const AtomicString& type, Document*);
Page* m_page; Page* m_page;
bool m_lockPending;
RefPtr<Element> m_element; RefPtr<Element> m_element;
RefPtr<Document> m_documentOfRemovedElementWhileWaitingForUnlock; RefPtr<Document> m_documentOfRemovedElementWhileWaitingForUnlock;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment