Files
sousa-gecko/dom/base/PointerLockManager.h
T
Edgar Chen d98f16e74d Bug 1255338 - Part 2: Reset pointer position for pointer lock from parent process; r=smaug
This is gated behind a new pref: dom.pointer-lock.reset-to-center-from-parent.enabled.
The patch preserves the original behavior as much as possible when the pref is off.
There are some changes that affect both code paths, but they are minor and
should not affect the main logic.

Here are some major change when the pref is enabled:
- Pointer recentering and computation of the center point are now handled in the parent process.
- Locking native pointer is initiated from parent process as well.
- When a remote target requests pointer lock, the parent process captures the mouse
  on the top-level browser element. This is necessary because the center of the
  chrome window may not correspond to the web page (for example, when a DevTools
  panel is open and resized to be very large).
- This patch introduces an optimization that recenters the pointer only when it
  moves within a 25% boundary buffer near the edge of the window, reducing the
  number of recentering operations. Since each platform now uses a native API to
  "lock" the pointer, we do not need to worry as much about the pointer escaping
  pointer lock by moving outside the browser window at high speed.

Differential Revision: https://phabricator.services.mozilla.com/D296321
2026-06-26 17:35:07 +00:00

104 lines
3.6 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_PointerLockManager_h
#define mozilla_PointerLockManager_h
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/RefPtr.h"
#include "nsIWeakReferenceUtils.h"
#include "nsThreadUtils.h"
namespace mozilla {
enum class StyleCursorKind : uint8_t;
namespace dom {
class BrowsingContext;
class BrowserParent;
enum class CallerType : uint32_t;
class Document;
class Element;
class Promise;
struct PointerLockOptions;
} // namespace dom
class PointerLockManager final {
public:
// https://w3c.github.io/pointerlock/#dom-element-requestpointerlock
// |aPromise| is the Promise returned to script; it is resolved when the
// lock is acquired and rejected with a DOMException matching the spec
// when any check fails.
static void RequestLock(dom::Element* aElement,
const dom::PointerLockOptions& aOptions,
dom::CallerType aCallerType, dom::Promise* aPromise);
MOZ_CAN_RUN_SCRIPT_BOUNDARY
static void Unlock(const char* aReason, dom::Document* aDoc = nullptr);
static bool IsLocked() { return sIsLocked; }
static already_AddRefed<dom::Element> GetLockedElement();
static already_AddRefed<dom::Document> GetLockedDocument();
static dom::BrowserParent* GetLockedRemoteTarget();
/**
* Returns true if aContext and the current pointer locked document
* have common top BrowsingContext.
* Note that this method returns true only if caller is in the same process
* as pointer locked document.
*/
static bool IsInLockContext(mozilla::dom::BrowsingContext* aContext);
// Set/release pointer lock remote target. Should only be called in parent
// process.
static void SetLockedRemoteTarget(dom::BrowserParent* aBrowserParent,
const bool& aUnadjustedMovement,
nsACString& aError);
static void ReleaseLockedRemoteTarget(dom::BrowserParent* aBrowserParent);
// Returns true if the pointer position should be reset for pointer lock in
// this process.
static bool ShouldResetPointer();
private:
class PointerLockRequest final : public Runnable {
public:
PointerLockRequest(dom::Element* aElement, bool aUserInputOrChromeCaller,
bool aUnadjustedMovement, dom::Promise* aPromise);
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() final;
private:
nsWeakPtr mElement;
nsWeakPtr mDocument;
bool mUserInputOrChromeCaller;
bool mUnadjustedMovement;
// Strong reference: the script-side lifetime of the returned Promise is
// independent of the requested element's lifetime, so we keep it alive
// until we resolve or reject it.
RefPtr<dom::Promise> mPromise;
};
static void ChangePointerLockedElement(dom::Element* aElement,
dom::Document* aDocument,
dom::Element* aPointerLockedElement);
MOZ_CAN_RUN_SCRIPT_BOUNDARY
static bool StartSetPointerLock(dom::Element* aElement,
dom::Document* aDocument,
bool aUnadjustedMovement);
MOZ_CAN_RUN_SCRIPT
static bool SetPointerLock(dom::Element* aElement, dom::Document* aDocument,
StyleCursorKind, bool aUnadjustedMovement);
static bool sIsLocked;
static bool sIsLockUnadjustedMovement;
};
} // namespace mozilla
#endif // mozilla_PointerLockManager_h