diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index 41f9ca7136fb80f0cfc17eedda45441dd75e473c..2b4f66d8900e992bed6197ce451dc96d8a9c282b 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -357,11 +357,12 @@ var pd_myversion, // Pd version string // Keycode vs Charcode: A Primer // ----------------------------- // * keycode is a unique number assigned to a physical key on the keyboard +// * keycode is device dependent // * charcode is the ASCII character (printable or otherwise) that gets output // when you depress a particular key // * keydown and keyup events report keycodes but not charcodes // * keypress events report charcodes but not keycodes -// * keypress events do _not_ report non-ASCII chars like arrow keys, +// * keypress events do _not_ fire for non-printing chars like arrow keys, // Alt keypress, Ctrl, (possibly) the keypad Delete key, and others // * in Pd, we want to send ASCII codes + arrow keys et al to Pd for // both keydown and keyup events @@ -369,13 +370,13 @@ var pd_myversion, // Pd version string // 1) keydown // 2) keypress // 3) keyup -// Therefore... -// * solution #1: we check for non-ASCII keycodes like arrow keys inside -// the keydown event -// * solution #2: in the keypress event, we map the charcode to the -// last keydown keycode we received -// * solution #3: on keyup, we use the keycode to look up the corresponding -// charcode, and send the charcode on to Pd +// Therefore are solution is: +// 1. We check for non-printable keycodes like arrow keys inside +// the keydown event. +// 2. In the keypress event, we map the charcode to the +// last keydown keycode we received. +// 3. On keyup, we use the keycode to look up the corresponding +// charcode, and send the charcode on to Pd var pd_keymap = {}; // to iteratively map keydown/keyup keys // to keypress char codes @@ -408,163 +409,183 @@ function cmd_or_ctrl_key(evt) { exports.cmd_or_ctrl_key = cmd_or_ctrl_key; -var last_keydown = ""; - -exports.keydown = function(cid, evt) { - var key_code = evt.keyCode, - hack = null, // hack for unprintable ascii codes - cmd_or_ctrl - switch(key_code) { - case 8: // backspace - case 9: - case 10: - case 27: - //case 32: - case 127: hack = key_code; break; - case 46: hack = 127; break; // some platforms report 46 for Delete - case 37: hack = add_keymods("Left", evt); break; - case 38: hack = add_keymods("Up", evt); break; - case 39: hack = add_keymods("Right", evt); break; - case 40: hack = add_keymods("Down", evt); break; - case 33: hack = add_keymods("Prior", evt); break; - case 34: hack = add_keymods("Next", evt); break; - case 35: hack = add_keymods("End", evt); break; - case 36: hack = add_keymods("Home", evt); break; - - // These may be different on Safari... - case 112: hack = add_keymods("F1", evt); break; - case 113: hack = add_keymods("F2", evt); break; - case 114: hack = add_keymods("F3", evt); break; - case 115: hack = add_keymods("F4", evt); break; - case 116: hack = add_keymods("F5", evt); break; - case 117: hack = add_keymods("F6", evt); break; - case 118: hack = add_keymods("F7", evt); break; - case 119: hack = add_keymods("F8", evt); break; - case 120: hack = add_keymods("F9", evt); break; - case 121: hack = add_keymods("F10", evt); break; - case 122: hack = add_keymods("F11", evt); break; - case 123: hack = add_keymods("F12", evt); break; - - // Handle weird behavior for clipboard shortcuts - // Which don't fire a keypress for some odd reason - - case 65: - if (cmd_or_ctrl_key(evt)) { // ctrl-a - // This is handled in the nwjs menu, but we - // add a way to toggle the window menubar - // the following command should be uncommented... - //pdsend(name, "selectall"); - hack = 0; // not sure what to report here... - } - break; - case 88: - if (cmd_or_ctrl_key(evt)) { // ctrl-x - // This is handled in the nwjs menubar. If we - // add a way to toggle the menubar it will be - // handled with the "cut" DOM listener, so we - // can probably remove this code... - //pdsend(name, "cut"); - hack = 0; // not sure what to report here... - } - break; - case 67: - if (cmd_or_ctrl_key(evt)) { // ctrl-c - // Handled in nwjs menubar (see above) - //pdsend(name, "copy"); - hack = 0; // not sure what to report here... - } - break; - case 86: - if (cmd_or_ctrl_key(evt)) { // ctrl-v - // We also use "cut" and "copy" DOM event handlers - // and leave this code in case we need to change - // tactics for some reason. - //pdsend(name, "paste"); - hack = 0; // not sure what to report here... - } - break; - case 90: - if (cmd_or_ctrl_key(evt)) { // ctrl-z undo/redo - // We have to catch undo and redo here. - // undo and redo have nw.js menu item shortcuts, - // and those shortcuts don't behave consistently - // across platforms: - // Gnu/Linux: key events for the shortcut do not - // propogate down to the DOM - // OSX: key events for the shortcut _do_ propogate - // down to the DOM - // Windows: not sure... - - // Solution-- let the menu item shortcuts handle - // undo/redo functionality, and do nothing here... - //if (evt.shiftKey) { - // pdsend(name, "redo"); - //} else { - // pdsend(name, "undo"); - //} - } - break; +(function () { + + var last_keydown = ""; + var keydown_repeat = 0; + + exports.keydown = function(cid, evt) { + var key_code = evt.keyCode, + hack = null, // hack for non-printable ascii codes + cmd_or_ctrl + switch(key_code) { + case 8: // backspace + case 9: + case 10: + case 27: + //case 32: + case 127: hack = key_code; break; + case 46: hack = 127; break; // some platforms report 46 for Delete + case 37: hack = add_keymods("Left", evt); break; + case 38: hack = add_keymods("Up", evt); break; + case 39: hack = add_keymods("Right", evt); break; + case 40: hack = add_keymods("Down", evt); break; + case 33: hack = add_keymods("Prior", evt); break; + case 34: hack = add_keymods("Next", evt); break; + case 35: hack = add_keymods("End", evt); break; + case 36: hack = add_keymods("Home", evt); break; + + // These may be different on Safari... + case 112: hack = add_keymods("F1", evt); break; + case 113: hack = add_keymods("F2", evt); break; + case 114: hack = add_keymods("F3", evt); break; + case 115: hack = add_keymods("F4", evt); break; + case 116: hack = add_keymods("F5", evt); break; + case 117: hack = add_keymods("F6", evt); break; + case 118: hack = add_keymods("F7", evt); break; + case 119: hack = add_keymods("F8", evt); break; + case 120: hack = add_keymods("F9", evt); break; + case 121: hack = add_keymods("F10", evt); break; + case 122: hack = add_keymods("F11", evt); break; + case 123: hack = add_keymods("F12", evt); break; + + // Handle weird behavior for clipboard shortcuts + // Which don't fire a keypress for some odd reason + + case 65: + if (cmd_or_ctrl_key(evt)) { // ctrl-a + // This is handled in the nwjs menu, but we + // add a way to toggle the window menubar + // the following command should be uncommented... + //pdsend(name, "selectall"); + hack = 0; // not sure what to report here... + } + break; + case 88: + if (cmd_or_ctrl_key(evt)) { // ctrl-x + // This is handled in the nwjs menubar. If we + // add a way to toggle the menubar it will be + // handled with the "cut" DOM listener, so we + // can probably remove this code... + //pdsend(name, "cut"); + hack = 0; // not sure what to report here... + } + break; + case 67: + if (cmd_or_ctrl_key(evt)) { // ctrl-c + // Handled in nwjs menubar (see above) + //pdsend(name, "copy"); + hack = 0; // not sure what to report here... + } + break; + case 86: + if (cmd_or_ctrl_key(evt)) { // ctrl-v + // We also use "cut" and "copy" DOM event handlers + // and leave this code in case we need to change + // tactics for some reason. + //pdsend(name, "paste"); + hack = 0; // not sure what to report here... + } + break; + case 90: + if (cmd_or_ctrl_key(evt)) { // ctrl-z undo/redo + // We have to catch undo and redo here. + // undo and redo have nw.js menu item shortcuts, + // and those shortcuts don't behave consistently + // across platforms: + // Gnu/Linux: key events for the shortcut do not + // propogate down to the DOM + // OSX: key events for the shortcut _do_ propogate + // down to the DOM + // Windows: not sure... + + // Solution-- let the menu item shortcuts handle + // undo/redo functionality, and do nothing here... + //if (evt.shiftKey) { + // pdsend(name, "redo"); + //} else { + // pdsend(name, "undo"); + //} + } + break; + + // Need to handle Control key, Alt + + case 16: hack = "Shift"; break; + case 17: hack = "Control"; break; + case 18: hack = "Alt"; break; - // Need to handle Control key, Alt + // keycode 55 = 7 key (shifted = '/' on German keyboards) + case 55: + if (cmd_or_ctrl_key(evt)) { + evt.preventDefault(); + pdsend("pd dsp 1"); + } + break; - case 16: hack = "Shift"; break; - case 17: hack = "Control"; break; - case 18: hack = "Alt"; break; + } + if (hack !== null) { + // To match Pd Vanilla behavior, fake a keyup if this + // is an auto-repeating key + if (evt.repeat) { + canvas_sendkey(cid, 0, evt, hack, 1); + } + canvas_sendkey(cid, 1, evt, hack, evt.repeat); + set_keymap(key_code, hack); + } - // keycode 55 = 7 key (shifted = '/' on German keyboards) - case 55: - if (cmd_or_ctrl_key(evt)) { - evt.preventDefault(); - pdsend("pd dsp 1"); + //post("keydown time: keycode is " + evt.keyCode); + last_keydown = evt.keyCode; + keydown_repeat = evt.repeat; + //evt.stopPropagation(); + //evt.preventDefault(); + }; + + exports.keypress = function(cid, evt) { + // For some reasons <ctrl-e> registers a keypress with + // charCode of 5. We filter that out here so it doesn't + // cause trouble when toggling editmode. + // Also, we're capturing <ctrl-or-cmd-Enter> in the "Edit" + // menu item "reselect", so we filter it out here as well. + // (That may change once we find a more flexible way of + // handling keyboard shortcuts + if (evt.charCode !== 5 && + (!cmd_or_ctrl_key(evt) || evt.charCode !== 10)) { + // To match Pd Vanilla behavior, fake a keyup if this + // is an auto-repeating key + if (keydown_repeat) { + canvas_sendkey(cid, 0, evt, evt.charCode, 1); } - break; + canvas_sendkey(cid, 1, evt, evt.charCode, + keydown_repeat); + set_keymap(last_keydown, evt.charCode, + keydown_repeat); + } + //post("keypress time: charcode is " + evt.charCode); + // Don't do things like scrolling on space, arrow keys, etc. + }; - } - if (hack !== null) { - canvas_sendkey(cid, 1, evt, hack, evt.repeat); - set_keymap(key_code, hack); - } + exports.keyup = function(cid, evt) { + var my_char_code = get_char_code(evt.keyCode); + // Sometimes we don't have char_code. For example, the + // nw menu doesn't propogate shortcut events, so we don't get + // to map a charcode on keydown/keypress. In those cases we'll + // get null, so we check for that here... + + // Also, HTML5 keyup event appears not to ever trigger on autorepeat. + // So we always send a zero here and fake the autorepeat above to + // maintain consistency with Pd Vanilla. + if (my_char_code) { + canvas_sendkey(cid, 0, evt, my_char_code, 0); + } + // This can probably be removed + //if (cmd_or_ctrl_key(evt) && + // (evt.keyCode === 13 || evt.keyCode === 10)) { + // pdgui.pdsend(name, "reselect"); + //} + }; - //post("keydown time: keycode is " + evt.keyCode); - last_keydown = evt.keyCode; - //evt.stopPropagation(); - //evt.preventDefault(); -}; - -exports.keypress = function(cid, evt) { - // For some reasons <ctrl-e> registers a keypress with - // charCode of 5. We filter that out here so it doesn't - // cause trouble when toggling editmode. - // Also, we're capturing <ctrl-or-cmd-Enter> in the "Edit" - // menu item "reselect", so we filter it out here as well. - // (That may change once we find a more flexible way of - // handling keyboard shortcuts - if (evt.charCode !== 5 && - (!cmd_or_ctrl_key(evt) || evt.charCode !== 10)) { - canvas_sendkey(cid, 1, evt, evt.charCode, - evt.repeat); - set_keymap(last_keydown, evt.charCode, - evt.repeat); - } - //post("keypress time: charcode is " + evt.charCode); - // Don't do things like scrolling on space, arrow keys, etc. -}; - -exports.keyup = function(cid, evt) { - var my_char_code = get_char_code(evt.keyCode); - // Sometimes we don't have char_code. For example, the - // nw menu doesn't propogate shortcut events, so we don't get - // to map a charcode on keydown/keypress. In those cases we'll - // get null, so we check for that here... - if (my_char_code) { - canvas_sendkey(cid, 0, evt, my_char_code, evt.repeat); - } - // This can probably be removed - //if (cmd_or_ctrl_key(evt) && - // (evt.keyCode === 13 || evt.keyCode === 10)) { - // pdgui.pdsend(name, "reselect"); - //} -}; +})(); // Hard-coded Pd-l2ork font metrics /*