aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Harris <bjh21@bjh21.me.uk>2023-07-05 19:39:57 +0100
committerBen Harris <bjh21@bjh21.me.uk>2023-07-05 19:39:57 +0100
commitad7042db989eb525defea9298b2b14d564498473 (patch)
tree2745e325e200d421f881ed28c555ea3a75f2a980
parentc8cc4a5f387774c35e3e8f924d4200c0908c9d5a (diff)
downloadpuzzles-ad7042db989eb525defea9298b2b14d564498473.zip
puzzles-ad7042db989eb525defea9298b2b14d564498473.tar.gz
puzzles-ad7042db989eb525defea9298b2b14d564498473.tar.bz2
puzzles-ad7042db989eb525defea9298b2b14d564498473.tar.xz
js: Copy-to-clipboard support
Now using the browser's "copy" operation while the focus is in the puzzle will copy the puzzle state to the clipboard. Browsers seem to have odd ideas about whate element to target with the "copy" event: Firefox targets the parent of the <canvas> while Chromium targets the <body>. To cope with these and possible future weirdness I attach the event handler to the document and then look to see if it's plausibly related to the canvas. Arguably we might want to handle a wider range of "copy" events, maybe any where the selection isn't empty. I'm not sure, though, so we'll start with the minimal change.
-rw-r--r--cmake/platforms/emscripten.cmake3
-rw-r--r--emcc.c12
-rw-r--r--emccpre.js20
3 files changed, 35 insertions, 0 deletions
diff --git a/cmake/platforms/emscripten.cmake b/cmake/platforms/emscripten.cmake
index b7e9c7d..e13366f 100644
--- a/cmake/platforms/emscripten.cmake
+++ b/cmake/platforms/emscripten.cmake
@@ -35,6 +35,9 @@ set(emcc_export_list
_timer_callback
# Callback from button presses in the UI outside the canvas
_command
+ # Text-formatting for copying to clipboard
+ _get_text_format
+ _free_text_format
# Game-saving and game-loading functions
_get_save_file
_free_save_file
diff --git a/emcc.c b/emcc.c
index 7d7a09b..2f82878 100644
--- a/emcc.c
+++ b/emcc.c
@@ -115,6 +115,8 @@ bool key(int keycode, const char *key, const char *chr, int location,
bool shift, bool ctrl);
void timer_callback(double tplus);
void command(int n);
+char *get_text_format(void);
+void free_save_file(char *buffer);
char *get_save_file(void);
void free_save_file(char *buffer);
void load_game(void);
@@ -880,6 +882,16 @@ void command(int n)
}
}
+char *get_text_format(void)
+{
+ return midend_text_format(me);
+}
+
+void free_text_format(char *buffer)
+{
+ sfree(buffer);
+}
+
/* ----------------------------------------------------------------------
* Called from JS to prepare a save-game file, and free one after it's
* been used.
diff --git a/emccpre.js b/emccpre.js
index 842a392..de94509 100644
--- a/emccpre.js
+++ b/emccpre.js
@@ -670,6 +670,26 @@ function initPuzzle() {
}
});
+ // Handle "copy" actions. Browsers don't reliably target the
+ // "copy" event at the canvas when it's focused. Firefox 102
+ // targets the containing <div> while Chromium 114 targets the
+ // <body>. So we catch the event at the document level and work
+ // out if it's relevant ourselves.
+ var get_text_format = Module.cwrap('get_text_format', 'number', []);
+ var free_text_format = Module.cwrap('free_text_format', 'void', ['number']);
+ document.addEventListener("copy", function(event) {
+ // Make sure the target is an ancestor of the canvas. And if
+ // there's a selection assume the user wants to copy that and
+ // not the puzzle.
+ if (event.target.contains(onscreen_canvas) &&
+ window.getSelection().isCollapsed) {
+ var ptr = get_text_format();
+ event.clipboardData.setData('text/plain', UTF8ToString(ptr));
+ event.preventDefault();
+ free_text_format(ptr);
+ }
+ });
+
// Event handler to fake :focus-within on browsers too old for
// it (like KaiOS 2.5). Browsers without :focus-within are also
// too old for focusin/out events, so we have to use focus events