diff --git a/lib/matplotlib/backends/backend_webagg_core.py b/lib/matplotlib/backends/backend_webagg_core.py index 32bb61258a3d..531fce3ada7c 100644 --- a/lib/matplotlib/backends/backend_webagg_core.py +++ b/lib/matplotlib/backends/backend_webagg_core.py @@ -47,6 +47,96 @@ def new_figure_manager_given_figure(num, figure): return manager +# http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes +_SHIFT_LUT = {59: ':', + 61: '+', + 173: '_', + 186: ':', + 187: '+', + 188: '<', + 189: '_', + 190: '>', + 191: '?', + 192: '~', + 219: '{', + 220: '|', + 221: '}', + 222: '"'} + +_LUT = {8: 'backspace', + 9: 'tab', + 13: 'enter', + 16: 'shift', + 17: 'control', + 18: 'alt', + 19: 'pause', + 20: 'caps', + 27: 'escape', + 32: ' ', + 33: 'pageup', + 34: 'pagedown', + 35: 'end', + 36: 'home', + 37: 'left', + 38: 'up', + 39: 'right', + 40: 'down', + 45: 'insert', + 46: 'delete', + 91: 'super', + 92: 'super', + 93: 'select', + 106: '*', + 107: '+', + 109: '-', + 110: '.', + 111: '/', + 144: 'num_lock', + 145: 'scroll_lock', + 186: ':', + 187: '=', + 188: ',', + 189: '-', + 190: '.', + 191: '/', + 192: '`', + 219: '[', + 220: '\\', + 221: ']', + 222: "'"} + + +def _handle_key(key): + """Handle key codes""" + code = int(key[key.index('k') + 1:]) + value = chr(code) + # letter keys + if code >= 65 and code <= 90: + if 'shift+' in key: + key = key.replace('shift+', '') + else: + value = value.lower() + # number keys + elif code >= 48 and code <= 57: + if 'shift+' in key: + value = ')!@#$%^&*('[int(value)] + key = key.replace('shift+', '') + # function keys + elif code >= 112 and code <= 123: + value = 'f%s' % (code - 111) + # number pad keys + elif code >= 96 and code <= 105: + value = '%s' % (code - 96) + # keys with shift alternatives + elif code in _SHIFT_LUT and 'shift+' in key: + key = key.replace('shift+', '') + value = _SHIFT_LUT[code] + elif code in _LUT: + value = _LUT[code] + key = key[:key.index('k')] + value + return key + + class FigureCanvasWebAggCore(backend_agg.FigureCanvasAgg): supports_blit = False @@ -221,8 +311,7 @@ def handle_event(self, event): elif e_type == 'scroll': self.scroll_event(x, y, event['step']) elif e_type in ('key_press', 'key_release'): - key = event['key'] - + key = _handle_key(event['key']) if e_type == 'key_press': self.key_press_event(key) elif e_type == 'key_release': diff --git a/lib/matplotlib/backends/web_backend/mpl.js b/lib/matplotlib/backends/web_backend/mpl.js index cebc8d12b76d..20a83a98be94 100644 --- a/lib/matplotlib/backends/web_backend/mpl.js +++ b/lib/matplotlib/backends/web_backend/mpl.js @@ -120,7 +120,7 @@ mpl.figure.prototype._init_canvas = function() { } canvas_div.keydown('key_press', canvas_keyboard_event); - canvas_div.keydown('key_release', canvas_keyboard_event); + canvas_div.keyup('key_release', canvas_keyboard_event); this.canvas_div = canvas_div this._canvas_extra_style(canvas_div) this.root.append(canvas_div); @@ -458,21 +458,35 @@ mpl.figure.prototype.mouse_event = function(event, name) { return false; } +mpl.figure.prototype._key_event_extra = function(event, name) { + // Handle any extra behaviour associated with a key event +} + mpl.figure.prototype.key_event = function(event, name) { - /* Don't fire events just when a modifier is changed. Modifiers are - sent along with other keys. */ - if (event.keyCode >= 16 && event.keyCode <= 20) { - return; + + // Prevent repeat events + if (name == 'key_press') + { + if (event.which === this._key) + return; + else + this._key = event.which; } + if (name == 'key_release') + this._key = null; var value = ''; - if (event.ctrlKey) { + if (event.ctrlKey && event.which != 17) value += "ctrl+"; - } - if (event.altKey) { + if (event.altKey && event.which != 18) value += "alt+"; - } - value += String.fromCharCode(event.keyCode).toLowerCase(); + if (event.shiftKey && event.which != 16) + value += "shift+"; + + value += 'k'; + value += event.which.toString(); + + this._key_event_extra(event, name); this.send_message(name, {key: value}); return false; diff --git a/lib/matplotlib/backends/web_backend/nbagg_mpl.js b/lib/matplotlib/backends/web_backend/nbagg_mpl.js index fa333ddc974f..cdc312b2ba46 100644 --- a/lib/matplotlib/backends/web_backend/nbagg_mpl.js +++ b/lib/matplotlib/backends/web_backend/nbagg_mpl.js @@ -149,6 +149,22 @@ mpl.figure.prototype._canvas_extra_style = function(el){ } +mpl.figure.prototype._key_event_extra = function(event, name) { + var manager = IPython.notebook.keyboard_manager; + if (!manager) + manager = IPython.keyboard_manager; + + // Check for shift+enter + if (event.shiftKey && event.which == 13) { + this.canvas_div.blur(); + event.shiftKey = false; + // Send a "J" for go to next cell + event.which = 74; + event.keyCode = 74; + manager.command_mode(); + manager.handle_keydown(event); + } +} mpl.figure.prototype.handle_save = function(fig, msg) { fig.ondownload(fig, null); diff --git a/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb b/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb index 9e795319bc81..a8525ea28ed5 100644 --- a/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb +++ b/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:7f7ec6a6e2a63837a45a88a501ba3c5b1eb88e744925456a9bfeb0d6faa896a5" + "signature": "sha256:a1ac68aba163c75eab3d1fc91aa4d9a8ca66b09159619563827a19967d96814b" }, "nbformat": 3, "nbformat_minor": 0, @@ -417,13 +417,23 @@ "evt = []\n", "colors = iter(itertools.cycle(['r', 'g', 'b', 'k', 'c']))\n", "def on_event(event):\n", + " if event.name.startswith('key'):\n", + " fig.suptitle('%s: %s' % (event.name, event.key))\n", + " elif event.name == 'scroll_event':\n", + " fig.suptitle('%s: %s' % (event.name, event.step))\n", + " else:\n", + " fig.suptitle('%s: %s' % (event.name, event.button))\n", " evt.append(event)\n", " ln.set_color(next(colors))\n", " fig.canvas.draw()\n", " fig.canvas.draw_idle()\n", + "\n", "fig.canvas.mpl_connect('button_press_event', on_event)\n", - "fig.canvas.mpl_connect('key_press_event', on_event)\n", + "fig.canvas.mpl_connect('button_release_event', on_event)\n", "fig.canvas.mpl_connect('scroll_event', on_event)\n", + "fig.canvas.mpl_connect('key_press_event', on_event)\n", + "fig.canvas.mpl_connect('key_release_event', on_event)\n", + "\n", "plt.show()" ], "language": "python",