shithub: puzzles

Download patch

ref: 5fae5ca0db6a263d385c05cb6cfef5e3e3b18630
parent: e6faebeb9a1856c9ea7140eb650b48ada0adc923
author: Ben Harris <bjh21@bjh21.me.uk>
date: Tue Oct 25 16:38:37 EDT 2022

js: Be more subtle about cancelling keydown events

Now we only cancel a keydown event if the C keyboard handler recognises
the key and passes it on to the midend.  This doesn't necessarily mean
that the midend has actually done anything with it, of course.  Still,
this is enough to allow F12 to open the developer tools even when the
input focus is on the puzzle.  It also allows for tabbing out of the
puzzle into the links below it.

--- a/emcc.c
+++ b/emcc.c
@@ -260,9 +260,10 @@
 }
 
 /*
- * Keyboard handler called from JS.
+ * Keyboard handler called from JS.  Returns true if the key was
+ * handled and hence the keydown event should be cancelled.
  */
-void key(int keycode, const char *key, const char *chr, int location,
+bool key(int keycode, const char *key, const char *chr, int location,
          bool shift, bool ctrl)
 {
     /* Key location constants from JavaScript. */
@@ -366,7 +367,9 @@
 
         midend_process_key(me, 0, 0, keyevent);
         update_undo_redo();
+        return true; /* We've probably handled the event. */
     }
+    return false; /* Event not handled, because we don't even recognise it. */
 }
 
 /*
--- a/emccpre.js
+++ b/emccpre.js
@@ -305,17 +305,17 @@
     };
 
     // Set up keyboard handlers. We call event.preventDefault()
-    // in the keydown handler. This means that
-    // while the canvas itself has focus, _all_ keypresses go only to
-    // the puzzle - so users of this puzzle collection in other media
+    // in the keydown handler if it looks like we might have
+    // done something with the key.  This means that users
+    // of this puzzle collection in other media
     // can indulge their instinct to press ^R for redo, for example,
     // without accidentally reloading the page.
-    key = Module.cwrap('key', 'void', ['number', 'string', 'string',
-                                       'number', 'number', 'number']);
+    key = Module.cwrap('key', 'boolean', ['number', 'string', 'string',
+                                          'number', 'number', 'number']);
     onscreen_canvas.onkeydown = function(event) {
-        key(event.keyCode, event.key, event.char, event.location,
-            event.shiftKey ? 1 : 0, event.ctrlKey ? 1 : 0);
-        event.preventDefault();
+        if (key(event.keyCode, event.key, event.char, event.location,
+                event.shiftKey ? 1 : 0, event.ctrlKey ? 1 : 0))
+            event.preventDefault();
     };
 
     // command() is a C function called to pass back events which