webkitPointerLockElement returns null when pointer lock request is pending.
authorscheib@chromium.org <scheib@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Sep 2012 17:31:32 +0000 (17:31 +0000)
committerscheib@chromium.org <scheib@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Sep 2012 17:31:32 +0000 (17:31 +0000)
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: https://svn.webkit.org/repository/webkit/trunk@127606 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/pointer-lock/locked-element-iframe-removed-from-dom-expected.txt
LayoutTests/pointer-lock/locked-element-iframe-removed-from-dom.html
LayoutTests/pointer-lock/pointerlockelement-null-when-pending-expected.txt [new file with mode: 0644]
LayoutTests/pointer-lock/pointerlockelement-null-when-pending.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/page/PointerLockController.cpp
Source/WebCore/page/PointerLockController.h

index 69f4988..58e2d29 100644 (file)
@@ -1,3 +1,17 @@
+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>
 
         [EFL][WK2] Provide implementation for TestRunner::pathToLocalResource()
index 1825186..c9da65c 100644 (file)
@@ -10,7 +10,7 @@ PASS targetIframe1.contentDocument.webkitPointerLockElement is targetDiv1
 PASS targetDiv1.parentElement.parentElement is targetIframe1.contentDocument.body
      Remove iframe & immediately lock target2. (main document 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 successfullyParsed is true
 
index d987d51..01f59ee 100644 (file)
@@ -38,7 +38,7 @@
             expectNoEvents("Remove iframe & immediately lock target2. (iframe handler)", targetIframe1.contentDocument);
             targetIframe1.parentElement.removeChild(targetIframe1);
             targetDiv2.webkitRequestPointerLock();
-            shouldBe("document.webkitPointerLockElement", "targetDiv2");
+            shouldBe("document.webkitPointerLockElement", "null");
             // doNextStep called by event handler.
         },
     ];
diff --git a/LayoutTests/pointer-lock/pointerlockelement-null-when-pending-expected.txt b/LayoutTests/pointer-lock/pointerlockelement-null-when-pending-expected.txt
new file mode 100644 (file)
index 0000000..3cfbbfc
--- /dev/null
@@ -0,0 +1,18 @@
+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
+
diff --git a/LayoutTests/pointer-lock/pointerlockelement-null-when-pending.html b/LayoutTests/pointer-lock/pointerlockelement-null-when-pending.html
new file mode 100644 (file)
index 0000000..7934286
--- /dev/null
@@ -0,0 +1,46 @@
+<!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>
index 7421815..a603afb 100644 (file)
@@ -1,3 +1,33 @@
+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>
 
         [chromium] Wire up scrollable sublayers in ScrollingCoordinatorChromium
index 1da1c81..49d00c5 100644 (file)
@@ -5872,7 +5872,7 @@ void Document::webkitExitPointerLock()
 
 Element* Document::webkitPointerLockElement() const
 {
-    if (!page())
+    if (!page() || page()->pointerLockController()->lockPending())
         return 0;
     if (Element* element = page()->pointerLockController()->element()) {
         if (element->document() == this)
index ad79609..ddbb84f 100644 (file)
@@ -62,6 +62,7 @@ void PointerLockController::requestPointerLock(Element* target)
         enqueueEvent(eventNames().webkitpointerlockchangeEvent, target);
         m_element = target;
     } else if (m_page->chrome()->client()->requestPointerLock()) {
+        m_lockPending = true;
         m_element = target;
     } else {
         enqueueEvent(eventNames().webkitpointerlockerrorEvent, target);
@@ -79,7 +80,7 @@ void PointerLockController::elementRemoved(Element* element)
         m_documentOfRemovedElementWhileWaitingForUnlock = m_element->document();
         // Set element null immediately to block any future interaction with it
         // including mouse events received before the unlock completes.
-        m_element = 0;
+        clearElement();
         requestPointerUnlock();
     }
 }
@@ -87,11 +88,16 @@ void PointerLockController::elementRemoved(Element* element)
 void PointerLockController::documentDetached(Document* document)
 {
     if (m_element && m_element->document() == document) {
-        m_element = 0;
+        clearElement();
         requestPointerUnlock();
     }
 }
 
+bool PointerLockController::lockPending() const
+{
+    return m_lockPending;
+}
+
 Element* PointerLockController::element() const
 {
     return m_element.get();
@@ -100,18 +106,19 @@ Element* PointerLockController::element() const
 void PointerLockController::didAcquirePointerLock()
 {
     enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element.get());
+    m_lockPending = false;
 }
 
 void PointerLockController::didNotAcquirePointerLock()
 {
     enqueueEvent(eventNames().webkitpointerlockerrorEvent, m_element.get());
-    m_element = 0;
+    clearElement();
 }
 
 void PointerLockController::didLosePointerLock()
 {
     enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element ? m_element->document() : m_documentOfRemovedElementWhileWaitingForUnlock.get());
-    m_element = 0;
+    clearElement();
     m_documentOfRemovedElementWhileWaitingForUnlock = 0;
 }
 
@@ -127,6 +134,12 @@ void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& e
         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)
 {
     if (element)
index a942f93..c820754 100644 (file)
@@ -48,6 +48,7 @@ public:
     void requestPointerUnlock();
     void elementRemoved(Element*);
     void documentDetached(Document*);
+    bool lockPending() const;
     Element* element() const;
 
     void didAcquirePointerLock();
@@ -57,9 +58,11 @@ public:
 
 private:
     explicit PointerLockController(Page*);
+    void clearElement();
     void enqueueEvent(const AtomicString& type, Element*);
     void enqueueEvent(const AtomicString& type, Document*);
     Page* m_page;
+    bool m_lockPending;
     RefPtr<Element> m_element;
     RefPtr<Document> m_documentOfRemovedElementWhileWaitingForUnlock;
 };