diff --git a/build/toolchain.emscripten.mak b/build/toolchain.emscripten.mak index ac6116fe5..5de7d76cf 100644 --- a/build/toolchain.emscripten.mak +++ b/build/toolchain.emscripten.mak @@ -105,7 +105,12 @@ _mp_hal_input \ _mp_import_name \ _mp_parse_compile_execute \ _get_clipboard_text \ +_set_clipboard_text \ +__ZN3Ion9Clipboard24fetchFromSystemClipboardEPcm \ +__ZN3Ion9Clipboard21sendToSystemClipboardEPKc \ __ZN3Ion9Clipboard4readEPcm \ +__ZN3Ion9Clipboard5writeEPKc \ +__ZN9Clipboard5storeEPKci \ __ZN9Clipboard10storedTextEv \ __ZN11LayoutField18privateHandleEventEN3Ion6Events5EventE \ __ZN11LayoutField11handleEventEN3Ion6Events5EventE \ diff --git a/escher/src/clipboard.cpp b/escher/src/clipboard.cpp index dc38d2d70..2dd6e54ab 100644 --- a/escher/src/clipboard.cpp +++ b/escher/src/clipboard.cpp @@ -15,7 +15,10 @@ void Clipboard::store(const char * storedText, int length) { } const char * Clipboard::storedText() { - Ion::Clipboard::read(m_textBuffer, TextField::maxBufferSize()); + const char * systemText = Ion::Clipboard::read(); + if (systemText) { + return systemText; + } /* In order to allow copy/paste of empty formulas, we need to add empty * layouts between empty system parenthesis. This way, when the expression diff --git a/ion/include/ion/clipboard.h b/ion/include/ion/clipboard.h index 92bbe0414..c60b9ece6 100644 --- a/ion/include/ion/clipboard.h +++ b/ion/include/ion/clipboard.h @@ -1,16 +1,15 @@ #ifndef ION_CLIPBOARD_H #define ION_CLIPBOARD_H -#include - namespace Ion { namespace Clipboard { /* Write the text to the system clipboard. */ void write(const char * text); -/* Fill the buffer with text from the system clipboard. */ -void read(char * buffer, size_t bufferSize); +/* Returns the system's clipboard text if it differs from the text previously + * copied, and nullptr otherwise. */ +const char * read(); } } diff --git a/ion/src/device/shared/drivers/clipboard.cpp b/ion/src/device/shared/drivers/clipboard.cpp index 88e321f9f..eaccc5bdb 100644 --- a/ion/src/device/shared/drivers/clipboard.cpp +++ b/ion/src/device/shared/drivers/clipboard.cpp @@ -6,6 +6,6 @@ namespace Ion { * On the device, the clipboard is fully handled by Escher::Clipboard. */ void Clipboard::write(const char * text) {} -void Clipboard::read(char * buffer, size_t bufferSize) {} +const char * Clipboard::read() { return nullptr; } } diff --git a/ion/src/simulator/Makefile b/ion/src/simulator/Makefile index 10f10fb1e..473c0c7b3 100644 --- a/ion/src/simulator/Makefile +++ b/ion/src/simulator/Makefile @@ -8,6 +8,7 @@ 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 \ diff --git a/ion/src/simulator/android/Makefile b/ion/src/simulator/android/Makefile index 210130d8a..3ccba89a9 100644 --- a/ion/src/simulator/android/Makefile +++ b/ion/src/simulator/android/Makefile @@ -6,7 +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 \ + clipboard_helper.cpp \ haptics.cpp \ ) diff --git a/ion/src/simulator/ios/Makefile b/ion/src/simulator/ios/Makefile index 7a52d972b..a6b114ad2 100644 --- a/ion/src/simulator/ios/Makefile +++ b/ion/src/simulator/ios/Makefile @@ -6,7 +6,7 @@ ion_src += $(addprefix ion/src/simulator/shared/, \ apple/language.m \ dummy/callback.cpp \ dummy/haptics_enabled.cpp \ - clipboard.cpp \ + clipboard_helper.cpp \ haptics.cpp \ ) diff --git a/ion/src/simulator/linux/Makefile b/ion/src/simulator/linux/Makefile index 304068aad..1ff0ebcff 100644 --- a/ion/src/simulator/linux/Makefile +++ b/ion/src/simulator/linux/Makefile @@ -16,7 +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 \ + clipboard_helper.cpp \ collect_registers_x86_64.s \ collect_registers.cpp \ haptics.cpp \ diff --git a/ion/src/simulator/macos/Makefile b/ion/src/simulator/macos/Makefile index 7b90d0525..a465b83c2 100644 --- a/ion/src/simulator/macos/Makefile +++ b/ion/src/simulator/macos/Makefile @@ -6,7 +6,7 @@ ion_src += $(addprefix ion/src/simulator/shared/, \ apple/language.m \ dummy/callback.cpp \ dummy/haptics_enabled.cpp \ - clipboard.cpp \ + clipboard_helper.cpp \ collect_registers_x86_64.s \ collect_registers.cpp \ haptics.cpp \ diff --git a/ion/src/simulator/shared/clipboard.cpp b/ion/src/simulator/shared/clipboard.cpp index 550b18d9d..5f596c1da 100644 --- a/ion/src/simulator/shared/clipboard.cpp +++ b/ion/src/simulator/shared/clipboard.cpp @@ -1,27 +1,33 @@ #include -#include +#include "clipboard_helper.h" +#include #include -/* This file implements the methods to access the system clipboard on all - * targets but the web simulator. */ - namespace Ion { +namespace Clipboard { -void Clipboard::write(const char * text) { +uint32_t localClipboardVersion; + +void write(const char * text) { /* FIXME : Handle the error if need be. */ - SDL_SetClipboardText(text); + sendToSystemClipboard(text); + localClipboardVersion = crc32Byte(reinterpret_cast(text), strlen(text)); } -void Clipboard::read(char * buffer, size_t bufferSize) { - if (!SDL_HasClipboardText()) { - buffer[0] = '\0'; - return; +const char * read() { + constexpr size_t bufferSize = 32768; + static char buffer[bufferSize]; + fetchFromSystemClipboard(buffer, bufferSize); + if (buffer[0] == '\0') { + return nullptr; } - char * text = SDL_GetClipboardText(); - if (text) { - strlcpy(buffer, text, bufferSize); - SDL_free(text); + + uint32_t version = crc32Byte(reinterpret_cast(buffer), strlen(buffer)); + if (version == localClipboardVersion) { + return nullptr; } + return buffer; } } +} diff --git a/ion/src/simulator/shared/clipboard_helper.cpp b/ion/src/simulator/shared/clipboard_helper.cpp new file mode 100644 index 000000000..f92316978 --- /dev/null +++ b/ion/src/simulator/shared/clipboard_helper.cpp @@ -0,0 +1,28 @@ +#include "clipboard_helper.h" +#include +#include + +namespace Ion { +namespace Clipboard { + +void sendToSystemClipboard(const char * text) { + SDL_SetClipboardText(text); +} + +void fetchFromSystemClipboard(char * buffer, size_t bufferSize) { + if (!SDL_HasClipboardText()) { + buffer[0] = '\0'; + return; + } + char * text = SDL_GetClipboardText(); + if (text) { + strlcpy(buffer, text, bufferSize); + } else { + buffer[0] = '\0'; + } + SDL_free(text); + +} + +} +} diff --git a/ion/src/simulator/shared/clipboard_helper.h b/ion/src/simulator/shared/clipboard_helper.h new file mode 100644 index 000000000..529b6bd3e --- /dev/null +++ b/ion/src/simulator/shared/clipboard_helper.h @@ -0,0 +1,15 @@ +#ifndef ION_CLIPBOARD_HELPER_H +#define ION_CLIPBOARD_HELPER_H + +#include + +namespace Ion { +namespace Clipboard { + +void sendToSystemClipboard(const char * text); +void fetchFromSystemClipboard(char * buffer, size_t bufferSize); + +} +} + +#endif diff --git a/ion/src/simulator/web/Makefile b/ion/src/simulator/web/Makefile index dcfcb44d8..4032ef4df 100644 --- a/ion/src/simulator/web/Makefile +++ b/ion/src/simulator/web/Makefile @@ -15,7 +15,7 @@ LDFLAGS += --pre-js ion/src/simulator/web/preamble_env.js ion_src += $(addprefix ion/src/simulator/web/, \ callback.cpp \ - clipboard.cpp \ + clipboard_helper.cpp \ helpers.cpp \ ) diff --git a/ion/src/simulator/web/clipboard.cpp b/ion/src/simulator/web/clipboard_helper.cpp similarity index 77% rename from ion/src/simulator/web/clipboard.cpp rename to ion/src/simulator/web/clipboard_helper.cpp index 1775e76ed..c23111087 100644 --- a/ion/src/simulator/web/clipboard.cpp +++ b/ion/src/simulator/web/clipboard_helper.cpp @@ -1,4 +1,4 @@ -#include +#include "../shared/clipboard_helper.h" #include #include #include @@ -48,20 +48,17 @@ EM_JS(void, get_clipboard_text, (char * buffer, uint32_t bufferSize, AsyncStatus }); namespace Ion { +namespace Clipboard { -void Clipboard::write(const char * text) { - /* FIXME : Handle the error if need be. */ +void sendToSystemClipboard(const char * text) { /* 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) { +void fetchFromSystemClipboard(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(bufferSize), &lock, AsyncStatus::Failure, AsyncStatus::Success); @@ -71,17 +68,7 @@ void Clipboard::read(char * buffer, size_t bufferSize) { 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); - } } } +} diff --git a/ion/src/simulator/windows/Makefile b/ion/src/simulator/windows/Makefile index 5c23860f9..70f6dc4ca 100644 --- a/ion/src/simulator/windows/Makefile +++ b/ion/src/simulator/windows/Makefile @@ -7,7 +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 \ + clipboard_helper.cpp \ haptics.cpp \ )