dreamlayers / em-dosbox

An Emscripten port of DOSBox
www.dosbox.com
GNU General Public License v2.0
1.22k stars 154 forks source link

How are keyboard events sent to dosbox? #22

Open napalm272 opened 9 years ago

napalm272 commented 9 years ago

I want to create some buttons that can be clicked on, and when these buttons are clicked, I want to send keyboard events to dosbox. I can't find a place to add this logic. I tried adding window.onkeypress. I get events before dosbox is loaded, after it's loaded I don't get any events anymore. Can you point out where I should be looking at?

Thanks

jbanes commented 9 years ago

It's surprisingly difficult to get browsers to trigger a keyboard event. However, after consulting various answers on the topic, the following code was what I came up with to solve the problem. See if it works for you:

function simulateKeyEvent(charCode, pressed) 
{
    var name = pressed ? "keydown" : "keyup";
    var event = document.createEvent('KeyboardEvent');
    var getter = {
        get: function() { return this.keyCodeVal; }
    };

    if(!element) return;

    // Chromium Hack
    Object.defineProperty(event, 'keyCode', getter);
    Object.defineProperty(event, 'which', getter);
    Object.defineProperty(event, 'charCode', getter);   

    if(event.initKeyboardEvent) 
    {
        event.initKeyboardEvent(name, true, true, document.defaultView, false, false, false, false, charCode, charCode);
    } 
    else 
    {
        event.initKeyEvent(name, true, true, document.defaultView, false, false, false, false, charCode, 0);
    }

    event.keyCodeVal = charCode;

    if(event.keyCode !== charCode) 
    {
        alert("keyCode mismatch " + event.keyCode + "(" + event.which + ")");
    }

    element.dispatchEvent(event);
}
napalm272 commented 9 years ago

Thanks for the response! What is element in this case? I tried using document and it didn't work.

jbanes commented 9 years ago

Ah, good question! Here's the code I have that sets element:

element = document.getElementById('canvas')

Basically, it should be a reference to the element that DOSBox is rendering into. The code dispatches events onto that element so that they can be captured by DOSBox.

napalm272 commented 9 years ago

Actually just using document also works! The trick is to send a keyup event shortly after a keydown event to simulate a keypress. Sending a keypress event directly doesn't work for some reason. Just sending keydown event also doesn't have the correct behavior, but I think I can work around that. Thanks!