summaryrefslogtreecommitdiff
path: root/Source/WebCore/page/PointerLockController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/page/PointerLockController.cpp')
-rw-r--r--Source/WebCore/page/PointerLockController.cpp103
1 files changed, 75 insertions, 28 deletions
diff --git a/Source/WebCore/page/PointerLockController.cpp b/Source/WebCore/page/PointerLockController.cpp
index 5d6f5a5ea..ded552ebd 100644
--- a/Source/WebCore/page/PointerLockController.cpp
+++ b/Source/WebCore/page/PointerLockController.cpp
@@ -25,81 +25,109 @@
#include "config.h"
#include "PointerLockController.h"
+#if ENABLE(POINTER_LOCK)
+
#include "Chrome.h"
#include "ChromeClient.h"
#include "Element.h"
#include "Event.h"
+#include "EventNames.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
+#include "RuntimeEnabledFeatures.h"
+#include "ScriptController.h"
#include "VoidCallback.h"
-#if ENABLE(POINTER_LOCK)
namespace WebCore {
-PointerLockController::PointerLockController(Page* page)
+PointerLockController::PointerLockController(Page& page)
: m_page(page)
{
}
-PassOwnPtr<PointerLockController> PointerLockController::create(Page* page)
-{
- return adoptPtr(new PointerLockController(page));
-}
-
void PointerLockController::requestPointerLock(Element* target)
{
- if (!target || !target->inDocument() || m_documentOfRemovedElementWhileWaitingForUnlock) {
- enqueueEvent(eventNames().webkitpointerlockerrorEvent, target);
+ if (!target || !target->isConnected() || m_documentOfRemovedElementWhileWaitingForUnlock) {
+ enqueueEvent(eventNames().pointerlockerrorEvent, target);
+ return;
+ }
+
+ if (m_documentAllowedToRelockWithoutUserGesture != &target->document() && !ScriptController::processingUserGesture()) {
+ enqueueEvent(eventNames().pointerlockerrorEvent, target);
return;
}
if (target->document().isSandboxed(SandboxPointerLock)) {
// FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
- target->document().addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked pointer lock on an element because the element's frame is sandboxed and the 'allow-pointer-lock' permission is not set.");
- enqueueEvent(eventNames().webkitpointerlockerrorEvent, target);
+ target->document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, ASCIILiteral("Blocked pointer lock on an element because the element's frame is sandboxed and the 'allow-pointer-lock' permission is not set."));
+ enqueueEvent(eventNames().pointerlockerrorEvent, target);
return;
}
if (m_element) {
if (&m_element->document() != &target->document()) {
- enqueueEvent(eventNames().webkitpointerlockerrorEvent, target);
+ enqueueEvent(eventNames().pointerlockerrorEvent, target);
return;
}
- enqueueEvent(eventNames().webkitpointerlockchangeEvent, target);
m_element = target;
- } else if (m_page->chrome().client().requestPointerLock()) {
+ enqueueEvent(eventNames().pointerlockchangeEvent, target);
+ } else {
m_lockPending = true;
m_element = target;
- } else {
- enqueueEvent(eventNames().webkitpointerlockerrorEvent, target);
+ if (!m_page.chrome().client().requestPointerLock()) {
+ clearElement();
+ enqueueEvent(eventNames().pointerlockerrorEvent, target);
+ }
}
}
void PointerLockController::requestPointerUnlock()
{
- return m_page->chrome().client().requestPointerUnlock();
+ if (!m_element)
+ return;
+
+ m_unlockPending = true;
+ m_page.chrome().client().requestPointerUnlock();
+}
+
+void PointerLockController::requestPointerUnlockAndForceCursorVisible()
+{
+ m_documentAllowedToRelockWithoutUserGesture = nullptr;
+
+ if (!m_element)
+ return;
+
+ m_unlockPending = true;
+ m_page.chrome().client().requestPointerUnlock();
+ m_forceCursorVisibleUponUnlock = true;
}
-void PointerLockController::elementRemoved(Element* element)
+void PointerLockController::elementRemoved(Element& element)
{
- if (m_element == element) {
+ if (m_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.
- clearElement();
requestPointerUnlock();
+ clearElement();
}
}
-void PointerLockController::documentDetached(Document* document)
+void PointerLockController::documentDetached(Document& document)
{
- if (m_element && &m_element->document() == document) {
- clearElement();
+ if (m_element && &m_element->document() == &document) {
+ m_documentOfRemovedElementWhileWaitingForUnlock = &m_element->document();
requestPointerUnlock();
+ clearElement();
}
}
+bool PointerLockController::isLocked() const
+{
+ return m_element && !m_lockPending;
+}
+
bool PointerLockController::lockPending() const
{
return m_lockPending;
@@ -112,21 +140,32 @@ Element* PointerLockController::element() const
void PointerLockController::didAcquirePointerLock()
{
- enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element.get());
+ enqueueEvent(eventNames().pointerlockchangeEvent, m_element.get());
m_lockPending = false;
+ m_forceCursorVisibleUponUnlock = false;
+ m_documentAllowedToRelockWithoutUserGesture = &m_element->document();
}
void PointerLockController::didNotAcquirePointerLock()
{
- enqueueEvent(eventNames().webkitpointerlockerrorEvent, m_element.get());
+ enqueueEvent(eventNames().pointerlockerrorEvent, m_element.get());
clearElement();
+ m_unlockPending = false;
}
void PointerLockController::didLosePointerLock()
{
- enqueueEvent(eventNames().webkitpointerlockchangeEvent, m_element ? &m_element->document() : m_documentOfRemovedElementWhileWaitingForUnlock.get());
+ if (!m_unlockPending)
+ m_documentAllowedToRelockWithoutUserGesture = nullptr;
+
+ enqueueEvent(eventNames().pointerlockchangeEvent, m_element ? &m_element->document() : m_documentOfRemovedElementWhileWaitingForUnlock.get());
clearElement();
- m_documentOfRemovedElementWhileWaitingForUnlock = 0;
+ m_unlockPending = false;
+ m_documentOfRemovedElementWhileWaitingForUnlock = nullptr;
+ if (m_forceCursorVisibleUponUnlock) {
+ m_forceCursorVisibleUponUnlock = false;
+ m_page.chrome().client().setCursorHiddenUntilMouseMoves(false);
+ }
}
void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType)
@@ -141,10 +180,18 @@ void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& e
m_element->dispatchMouseEvent(event, eventNames().clickEvent, event.clickCount());
}
+void PointerLockController::dispatchLockedWheelEvent(const PlatformWheelEvent& event)
+{
+ if (!m_element || !m_element->document().frame())
+ return;
+
+ m_element->dispatchWheelEvent(event);
+}
+
void PointerLockController::clearElement()
{
m_lockPending = false;
- m_element = 0;
+ m_element = nullptr;
}
void PointerLockController::enqueueEvent(const AtomicString& type, Element* element)