3
votes

I have emscripten compiled c++ code (using openGL) that runs in my webpage(converted to WebGL) and renders an image. Everything is working great, Except that the Emscripten compiled Javascript blocks my usage of the "delete" "backspace" "tab" keys when I type into a textarea on the webpage. Note that all the letter keys and "space" work just fine.

For reference, the Module I have instantiated in my JavaScript code is almost exactly the same as the default module:

var Module = {
preRun: [],

postRun: [],

print: (function() {
    var element = document.getElementById('emscriptenOutput');
    if (element) element.value = ''; // clear browser cache
        return function(text) {
    if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
        // These replacements are necessary if you render to raw HTML
        //text = text.replace(/&/g, "&");
        //text = text.replace(/</g, "<");
        //text = text.replace(/>/g, ">");
        //text = text.replace('\n', '<br>', 'g');
        console.log(text);
        if (element) {
            element.value += text + "\n";
            element.scrollTop = element.scrollHeight; // focus on bottom
        }
    };
})(),

printErr: function(text) {
    if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
        if (0) { // XXX disabled for safety typeof dump == 'function') {
            dump(text + '\n'); // fast, straight to the real console
        } else {
            console.error(text);
    }
},

canvas: (function() {
    var canvas = document.getElementById('canvas');

    // As a default initial behavior, pop up an alert when webgl context is lost. To make your
    // application robust, you may want to override this behavior before shipping!
    // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
    canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
    return canvas;
})(),

totalDependencies: 0,

    //doNotCaptureKeyboard: true,

    monitorRunDependencies: function(left) {
        this.totalDependencies = Math.max(this.totalDependencies, left);
        // Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
    }
};

    (function() {
        var memoryInitializer = 'renderer.js.mem';
        if (typeof Module['locateFile'] === 'function') {
            memoryInitializer = Module['locateFile'](memoryInitializer);
        } else if (Module['memoryInitializerPrefixURL']) {
            memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
        }
        var meminitXHR = Module['memoryInitializerRequest'] = new XMLHttpRequest();
        meminitXHR.open('GET', memoryInitializer, true);
        meminitXHR.responseType = 'arraybuffer';
        meminitXHR.send(null);
    })();

    var script = document.createElement('script');
    script.src = "renderer.js";
    document.body.appendChild(script);

Ofcourse, the emscripten compiled JavaScript is gibberish to the human eye but the culprit most likely lies in there.

My guess is that the WebGL context is eating the keyboard events, but I'm not sure. I've looked at these links and tried to include "doNotCaptureKeyboard: true" to the module element, but with no success.

https://forum.unity.com/threads/disable-enable-keyboard-in-runtime-webgl.286557/#post-1892527 https://github.com/kripken/emscripten/issues/2668#event-154218404

Anyone have any experience with the same sort of issue? I'm at a loss.

2

2 Answers

0
votes

For those curious, I've got a solution but not sure if it's the best. I've just added event listeners of my own to block the event listeners of the compiled JavaScript code:

/* code to prevent emscripten compiled code from eating key input */
window.addEventListener('keydown', function(event){
    event.stopImmediatePropagation();
}, true);

window.addEventListener('keyup', function(event){
    event.stopImmediatePropagation();
}, true);
0
votes

Inside emscripten src/library_glfw.js (around line 400, milage might vary on your version) there's a very bizarre check that goes like this:

      // This logic comes directly from the sdl implementation. We cannot
      // call preventDefault on all keydown events otherwise onKeyPress will
      // not get called
      if (event.keyCode === 8 /* backspace */ || event.keyCode === 9 /* tab */) {
        event.preventDefault();
      }

Now If you comment out those lines those events will get propagated correctly, I'm not sure why they've put that SDL special case inside a generic code path.

PS: This answer will probably be outdated if they ever fix that bit of code, so if you are reading it from the future just use it as a past reference.