Search code examples
javascriptpointerslockingjupyterpointerlock

Activate pointerLock in a Jupyter notebook


I'm currently trying to use the Pointer Lock API into a Jupyter notebook. Basically I want to log a bunch of trackpad moves without being limited by the dimensions of the screen, then pass it on to Python to do some calculations on it. In what follow I'll just talk about getting the pointer lock.

Here's my approach: I create a new <div> on top of the current notebook so I can use it to lock the pointer, let's call it canvas, and call canvas.requestPointerLock();. Pretty straightforward stuff.

My concern is that the same code (below) will work fine in a Javascript tester, but not in a Jupyter cell in %%javascript mode.

var canvas = document.getElementById('canvasPA');
if (canvas !== null && typeof(canvas) != 'undefined') {
    canvas.parentNode.removeChild(canvas);
}

/*
 *  Checking whether the web page can accommodate pointerLock
 */
var havePointerLock = 'pointerLockElement' in document
        || 'mozPointerLockElement' in document
        || 'webkitPointerLockElement' in document;
if (havePointerLock) {
    console.log("Document has pointer lock capabilities."); // >> True
}

/*
 *  Defining the canvasPA div
 */
if (canvas === null || typeof(canvas) == 'undefined') {
    console.log("New canvas.");
    canvas = document.createElement('div');
    canvas.id = 'canvasPA';
    canvas.style = 'position: absolute; top: 250px; left: 550px; '
            + 'width: 1000px; height: 400px; '
            + 'background-color: #00BB5511; z-index: 1000;';
    document.getElementsByTagName('body')[0].appendChild(canvas);
}

/*
 *  Defining the changePointerLock behavior. 
 *  When the lock is released, all listeners are removed, then canvasPA is 
 *  removed from the webpage.
 */
function changeCallback() {

    var pointerLockElement = document.pointerLockElement 
            || document.mozPointerLockElement 
            || document.webkitPointerLockElement;
    console.log( "pointerLockElement: " + pointerLockElement );

    if(pointerLockElement === canvas) {

        console.log('The pointer lock status is now locked onto canvas');

    } else {
        console.log('The pointer lock status is now unlocked');  

        // Removing all pointerLock-related listeners
        document.removeEventListener('pointerlockchange', changeCallback, false);
        document.removeEventListener('mozpointerlockchange', changeCallback, false);
        document.removeEventListener('webkitpointerlockchange', changeCallback, false);
        document.removeEventListener('pointerlockerror', errorCallback, false);
        document.removeEventListener('mozpointerlockerror', errorCallback, false);
        document.removeEventListener('webkitpointerlockerror', errorCallback, false);

        // Remove canvas from the notebook
        canvas = document.getElementById("canvasPA");
        if (canvas !== null 
                && typeof(canvas) != 'undefined' 
                && canvas.parentNode !== null) {
            canvas.parentNode.removeChild(canvas);
        }
    }
}

function errorCallback() {
    console.log("Error when attempting to lock cursor...");
}

document.addEventListener('pointerlockchange', changeCallback, false);
document.addEventListener('mozpointerlockchange', changeCallback, false);
document.addEventListener('webkitpointerlockchange', changeCallback, false);
document.addEventListener('pointerlockerror', errorCallback, false);
document.addEventListener('mozpointerlockerror', errorCallback, false);
document.addEventListener('webkitpointerlockerror', errorCallback, false);

// Ask the browser to lock the pointer.
canvas.requestPointerLock = canvas.requestPointerLock 
        || canvas.mozRequestPointerLock 
        || canvas.webkitRequestPointerLock;
canvas.requestPointerLock();

With the Javascript tester my console prints:

Document has pointer lock capabilities. New canvas. pointerLockElement: [object HTMLDivElement] The pointer lock status is now locked onto canvas

Then the cursor is locked and disappears. Then I press Escape, and the console logs:

pointerLockElement: undefined The pointer lock status is now unlocked

However, when I try the exact same code in a Jupyter cell, I get:

Document has pointer lock capabilities. New canvas. Error when attempting to lock cursor...

And the cursor is never locked.

It would appear that something in a Jupyter notebook is preventing me to get the lock, but I cannot know for sure since the pointerlockerror comes with no explanation. Any thoughts?

I'm using Chrome (64.0.3282.140), Mac OS X 10.11.6.

Thanks a lot!

- Mathiev


Solution

  • So, I managed to make it work using this previous answer to a slightly different question:

    https://stackoverflow.com/a/19901534/9349369

    The problem is that requestPointerLock cannot be called automatically, it should be called from the user's callback

    It worked for me, I now call requestPointerLock() from a mouseclick callback.

    Glad that I found a solution, however I think the main question remains: how come it worked in "normal" javascript (see original question) and not from a Jupyter cell? I suppose that's less important now...