mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[ion/clipboard] Add support for web simulator
Wrote methods for accessing the system clipboard from the web simulator, as the methods in SDL_Clipboard do not work when the video device uses emscripten. Change-Id: Ib2e66530a6b013eca0cf69fb52372e9e3a21c8bb
This commit is contained in:
committed by
Émilie Feral
parent
b9c34ace3a
commit
010b474f77
@@ -77,6 +77,7 @@ _closure_call \
|
||||
_do_load \
|
||||
_do_load_from_lexer \
|
||||
_emscripten_sleep \
|
||||
_emscripten_sleep_with_yield \
|
||||
_fun_bc_call \
|
||||
_fun_builtin_1_call \
|
||||
_fun_builtin_var_call \
|
||||
@@ -103,6 +104,14 @@ _mp_execute_bytecode \
|
||||
_mp_hal_input \
|
||||
_mp_import_name \
|
||||
_mp_parse_compile_execute \
|
||||
_get_clipboard_text \
|
||||
__ZN3Ion9Clipboard4readEPcm \
|
||||
__ZN9Clipboard10storedTextEv \
|
||||
__ZN11LayoutField18privateHandleEventEN3Ion6Events5EventE \
|
||||
__ZN11LayoutField11handleEventEN3Ion6Events5EventE \
|
||||
__ZN8TextArea18privateHandleEventEN3Ion6Events5EventE \
|
||||
__ZN8TextArea11handleEventEN3Ion6Events5EventE \
|
||||
__ZN15ExpressionField11handleEventEN3Ion6Events5EventE \
|
||||
_msleep
|
||||
|
||||
EMTERPRETIFY_WHITELIST = $(foreach sym,$(EMSCRIPTEN_ASYNC_SYMBOLS),"$(sym)",)END
|
||||
|
||||
@@ -8,7 +8,6 @@ ion_src += $(addprefix ion/src/simulator/shared/, \
|
||||
dummy/serial_number.cpp \
|
||||
dummy/stack.cpp \
|
||||
dummy/usb.cpp \
|
||||
clipboard.cpp \
|
||||
console_stdio.cpp:-consoledisplay \
|
||||
crc32.cpp \
|
||||
display.cpp:-headless \
|
||||
|
||||
@@ -6,6 +6,7 @@ ion_src += $(addprefix ion/src/simulator/android/src/cpp/, \
|
||||
ion_src += $(addprefix ion/src/simulator/shared/, \
|
||||
dummy/callback.cpp \
|
||||
dummy/language.cpp \
|
||||
clipboard.cpp \
|
||||
haptics.cpp \
|
||||
)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ ion_src += $(addprefix ion/src/simulator/shared/, \
|
||||
apple/language.m \
|
||||
dummy/callback.cpp \
|
||||
dummy/haptics_enabled.cpp \
|
||||
clipboard.cpp \
|
||||
haptics.cpp \
|
||||
)
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ ion_src += $(addprefix ion/src/simulator/linux/, \
|
||||
ion_src += $(addprefix ion/src/simulator/shared/, \
|
||||
dummy/callback.cpp \
|
||||
dummy/haptics_enabled.cpp \
|
||||
clipboard.cpp \
|
||||
collect_registers_x86_64.s \
|
||||
collect_registers.cpp \
|
||||
haptics.cpp \
|
||||
|
||||
@@ -6,6 +6,7 @@ ion_src += $(addprefix ion/src/simulator/shared/, \
|
||||
apple/language.m \
|
||||
dummy/callback.cpp \
|
||||
dummy/haptics_enabled.cpp \
|
||||
clipboard.cpp \
|
||||
collect_registers_x86_64.s \
|
||||
collect_registers.cpp \
|
||||
haptics.cpp \
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#include <SDL.h>
|
||||
#include <string.h>
|
||||
|
||||
/* This file implements the methods to access the system clipboard on all
|
||||
* targets but the web simulator. */
|
||||
|
||||
namespace Ion {
|
||||
|
||||
void Clipboard::write(const char * text) {
|
||||
|
||||
@@ -15,6 +15,7 @@ LDFLAGS += --pre-js ion/src/simulator/web/preamble_env.js
|
||||
|
||||
ion_src += $(addprefix ion/src/simulator/web/, \
|
||||
callback.cpp \
|
||||
clipboard.cpp \
|
||||
helpers.cpp \
|
||||
)
|
||||
|
||||
|
||||
87
ion/src/simulator/web/clipboard.cpp
Normal file
87
ion/src/simulator/web/clipboard.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <ion/clipboard.h>
|
||||
#include <emscripten.h>
|
||||
#include <SDL.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
enum class AsyncStatus : uint32_t {
|
||||
Pending,
|
||||
Success,
|
||||
Failure
|
||||
};
|
||||
|
||||
/* When using emscripten, the SDL_Clipboard methods do not interact with the
|
||||
* system clipboard, but only with an internal buffer. We thus need to
|
||||
* implement our own methods via the JavaScript API.
|
||||
* However, we still call the SDL_Clipboard methods as a fallback to preserve
|
||||
* the copy-paste feature in case of calls to set_clipboard_text and
|
||||
* get_clipboard_text failing. */
|
||||
|
||||
EM_JS(void, set_clipboard_text, (const char * text, AsyncStatus * status, AsyncStatus failure, AsyncStatus success), {
|
||||
try {
|
||||
navigator.clipboard.writeText(UTF8ToString(text)).then(
|
||||
function () { HEAP32[status>>2] = success; },
|
||||
function () { HEAP32[status>>2] = failure; }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
HEAP32[status>>2] = failure;
|
||||
}
|
||||
});
|
||||
|
||||
EM_JS(void, get_clipboard_text, (char * buffer, uint32_t bufferSize, AsyncStatus * status, AsyncStatus failure, AsyncStatus success), {
|
||||
try {
|
||||
navigator.clipboard.readText().then(
|
||||
function(text) {
|
||||
var lenghtBytes = Math.min(lengthBytesUTF8(text) + 1, bufferSize);
|
||||
stringToUTF8(text, buffer, lenghtBytes);
|
||||
HEAP32[status>>2] = success;
|
||||
},
|
||||
function(text) { HEAP32[status>>2] = failure; }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
HEAP32[status>>2] = failure;
|
||||
}
|
||||
});
|
||||
|
||||
namespace Ion {
|
||||
|
||||
void Clipboard::write(const char * text) {
|
||||
/* FIXME : Handle the error if need be. */
|
||||
/* As the rest of the execution does not depend on the system clipboard being
|
||||
* properly filled at this point, the call to set_clipboard_text does not
|
||||
* need to be made synchronous. */
|
||||
AsyncStatus lock;
|
||||
set_clipboard_text(text, &lock, AsyncStatus::Failure, AsyncStatus::Success);
|
||||
/* Store a local copy of the text in case the browser does not grant access
|
||||
* to the clipboard. */
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
void Clipboard::read(char * buffer, size_t bufferSize) {
|
||||
AsyncStatus lock = AsyncStatus::Pending;
|
||||
static_assert(sizeof(size_t) <= sizeof(uint32_t), "Cast from size_t to uint32_t may overflow.");
|
||||
get_clipboard_text(buffer, static_cast<uint32_t>(bufferSize), &lock, AsyncStatus::Failure, AsyncStatus::Success);
|
||||
while (lock == AsyncStatus::Pending) {
|
||||
emscripten_sleep_with_yield(10);
|
||||
}
|
||||
if (lock == AsyncStatus::Success) {
|
||||
return;
|
||||
}
|
||||
/* If the browser does not grant access to the clipboard, read from a local
|
||||
* copy to at least maintain the basic copy-paste functionnality. */
|
||||
if (!SDL_HasClipboardText()) {
|
||||
buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
char * text = SDL_GetClipboardText();
|
||||
if (text) {
|
||||
strlcpy(buffer, text, bufferSize);
|
||||
SDL_free(text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ ion_src += $(addprefix ion/src/simulator/windows/, \
|
||||
ion_src += $(addprefix ion/src/simulator/shared/, \
|
||||
dummy/callback.cpp \
|
||||
dummy/haptics_enabled.cpp \
|
||||
clipboard.cpp \
|
||||
haptics.cpp \
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user