diff --git a/src/Input.c b/src/Input.c index 068519c0d..d3123d4fc 100644 --- a/src/Input.c +++ b/src/Input.c @@ -215,6 +215,12 @@ void Input_SetPressed(int key) { Input_Pressed[key] = true; Event_RaiseInput(&InputEvents.Down, key, wasPressed); +#ifndef CC_BUILD_WEB + /* Webclient needs special handling for clipboard copy/paste */ + if (key == 'C' && Key_IsActionPressed()) Event_RaiseInput(&InputEvents.Down, INPUT_CLIPBOARD_COPY, 0); + if (key == 'V' && Key_IsActionPressed()) Event_RaiseInput(&InputEvents.Down, INPUT_CLIPBOARD_PASTE, 0); +#endif + /* don't allow multiple left mouse down events */ if (key != KEY_LMOUSE || wasPressed) return; Pointer_SetPressed(0, true); diff --git a/src/Input.h b/src/Input.h index 754066a8e..7eea2bce0 100644 --- a/src/Input.h +++ b/src/Input.h @@ -44,7 +44,10 @@ enum InputButtons { /* NOTE: RMOUSE must be before MMOUSE for PlayerClick compatibility */ KEY_XBUTTON1, KEY_XBUTTON2, KEY_LMOUSE, KEY_RMOUSE, KEY_MMOUSE, - INPUT_COUNT + INPUT_COUNT, + + INPUT_CLIPBOARD_COPY = 1001, + INPUT_CLIPBOARD_PASTE = 1002 }; /* Simple names for each input button. */ diff --git a/src/LWidgets.c b/src/LWidgets.c index 974db27f6..c916fb621 100644 --- a/src/LWidgets.c +++ b/src/LWidgets.c @@ -438,13 +438,16 @@ static void LInput_Unselect(void* widget, int idx) { Window_CloseKeyboard(); } -static void LInput_CopyFromClipboard(cc_string* text, void* widget) { - struct LInput* w = (struct LInput*)widget; - String_UNSAFE_TrimStart(text); - String_UNSAFE_TrimEnd(text); +static void LInput_CopyFromClipboard(struct LInput* w) { + cc_string text; char textBuffer[2048]; + String_InitArray(text, textBuffer); - if (w->ClipboardFilter) w->ClipboardFilter(text); - LInput_AppendString(w, text); + Clipboard_GetText(&text); + String_UNSAFE_TrimStart(&text); + String_UNSAFE_TrimEnd(&text); + + if (w->ClipboardFilter) w->ClipboardFilter(&text); + LInput_AppendString(w, &text); } static void LInput_KeyDown(void* widget, int key, cc_bool was) { @@ -453,10 +456,10 @@ static void LInput_KeyDown(void* widget, int key, cc_bool was) { LInput_Backspace(w); } else if (key == KEY_DELETE) { LInput_Delete(w); - } else if (key == 'C' && Key_IsActionPressed()) { + } else if (key == INPUT_CLIPBOARD_COPY) { if (w->text.length) Clipboard_SetText(&w->text); - } else if (key == 'V' && Key_IsActionPressed()) { - Clipboard_RequestText(LInput_CopyFromClipboard, w); + } else if (key == INPUT_CLIPBOARD_PASTE) { + LInput_CopyFromClipboard(w); } else if (key == KEY_ESCAPE) { LInput_Clear(w); } else if (key == KEY_LEFT) { diff --git a/src/Widgets.c b/src/Widgets.c index b34e41349..910830f65 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -1216,18 +1216,20 @@ static void InputWidget_EndKey(struct InputWidget* w) { InputWidget_UpdateCaret(w); } -static void InputWidget_CopyFromClipboard(cc_string* text, void* w) { - InputWidget_AppendText((struct InputWidget*)w, text); +static void InputWidget_CopyFromClipboard(struct InputWidget* w) { + cc_string text; char textBuffer[2048]; + String_InitArray(text, textBuffer); + + Clipboard_GetText(&text); + InputWidget_AppendText(w, &text); } static cc_bool InputWidget_OtherKey(struct InputWidget* w, int key) { int maxChars = w->GetMaxLines() * INPUTWIDGET_LEN; - if (!Key_IsActionPressed()) return false; - - if (key == 'V' && w->text.length < maxChars) { - Clipboard_RequestText(InputWidget_CopyFromClipboard, w); + if (key == INPUT_CLIPBOARD_PASTE && w->text.length < maxChars) { + InputWidget_CopyFromClipboard(w); return true; - } else if (key == 'C') { + } else if (key == INPUT_CLIPBOARD_COPY) { if (!w->text.length) return true; Clipboard_SetText(&w->text); return true; diff --git a/src/Window.c b/src/Window.c index c1cd3d604..3a1ff38d6 100644 --- a/src/Window.c +++ b/src/Window.c @@ -16,17 +16,7 @@ struct _WinData WindowInfo; int Display_ScaleX(int x) { return (int)(x * DisplayInfo.ScaleX); } int Display_ScaleY(int y) { return (int)(y * DisplayInfo.ScaleY); } #define Display_CentreX(width) (DisplayInfo.X + (DisplayInfo.Width - width) / 2) -#define Display_CentreY(height) (DisplayInfo.Y + (DisplayInfo.Height - height) / 2) - -#ifndef CC_BUILD_WEB -void Clipboard_RequestText(RequestClipboardCallback callback, void* obj) { - cc_string text; char textBuffer[2048]; - String_InitArray(text, textBuffer); - - Clipboard_GetText(&text); - callback(&text, obj); -} -#endif +#define Display_CentreY(height) (DisplayInfo.Y + (DisplayInfo.Height - height) / 2) #ifdef CC_BUILD_IOS /* iOS implements some functions in external interop_ios.m file */ @@ -3560,23 +3550,32 @@ void Window_Init(void) { DisplayInfo.ScaleY = DisplayInfo.ScaleX; /* Copy text, but only if user isn't selecting something else on the webpage */ - /* (don't check window.clipboardData here, that's handled in Clipboard_SetText instead) */ EM_ASM(window.addEventListener('copy', function(e) { if (window.getSelection && window.getSelection().toString()) return; - if (window.cc_copyText) { - if (e.clipboardData) { e.clipboardData.setData('text/plain', window.cc_copyText); } + ccall('Window_ReqClipboardText', 'void'); + if (!window.cc_copyText) return; + + if (window.clipboardData) { + window.clipboardData.setData('Text', window.cc_copyText); + } else if (e.clipboardData) { + e.clipboardData.setData('text/plain', window.cc_copyText); e.preventDefault(); - window.cc_copyText = null; - } + } + window.cc_copyText = null; }); ); - /* Paste text (window.clipboardData is handled in Clipboard_RequestText instead) */ + /* Paste text */ EM_ASM(window.addEventListener('paste', function(e) { - var contents = e.clipboardData ? e.clipboardData.getData('text/plain') : ""; - ccall('Window_GotClipboardText', 'void', ['string'], [contents]); + if (window.clipboardData) { + var contents = window.clipboardData.getData('Text'); + ccall('Window_GotClipboardText', 'void', ['string'], [contents]); + } else if (e.clipboardData) { + var contents = e.clipboardData.getData('text/plain'); + ccall('Window_GotClipboardText', 'void', ['string'], [contents]); + } }); ); @@ -3632,46 +3631,23 @@ void Window_SetTitle(const cc_string* title) { EM_ASM_({ document.title = UTF8ToString($0); }, str); } -static RequestClipboardCallback clipboard_func; -static void* clipboard_obj; - -EMSCRIPTEN_KEEPALIVE void Window_GotClipboardText(char* src) { - cc_string str; char strBuffer[512]; - if (!clipboard_func) return; - - String_InitArray(str, strBuffer); - String_AppendUtf8(&str, src, String_CalcLen(src, 2048)); - clipboard_func(&str, clipboard_obj); - clipboard_func = NULL; +static char pasteBuffer[512]; +static cc_string pasteStr; +EMSCRIPTEN_KEEPALIVE void Window_ReqClipboardText(void) { + Event_RaiseInput(&InputEvents.Down, INPUT_CLIPBOARD_COPY, 0); } -void Clipboard_GetText(cc_string* value) { } +EMSCRIPTEN_KEEPALIVE void Window_GotClipboardText(char* src) { + String_InitArray(pasteStr, pasteBuffer); + String_AppendUtf8(&pasteStr, src, String_CalcLen(src, 2048)); + Event_RaiseInput(&InputEvents.Down, INPUT_CLIPBOARD_PASTE, 0); +} + +void Clipboard_GetText(cc_string* value) { String_Copy(value, &pasteStr); } void Clipboard_SetText(const cc_string* value) { char str[NATIVE_STR_LEN]; Platform_EncodeUtf8(str, value); - - /* For IE11, use window.clipboardData to set the clipboard */ - /* For other browsers, instead use the window.copy events */ - EM_ASM_({ - if (window.clipboardData) { - if (window.getSelection && window.getSelection().toString()) return; - window.clipboardData.setData('Text', UTF8ToString($0)); - } else { - window.cc_copyText = UTF8ToString($0); - } - }, str); -} - -void Clipboard_RequestText(RequestClipboardCallback callback, void* obj) { - clipboard_func = callback; - clipboard_obj = obj; - - /* For IE11, use window.clipboardData to get the clipboard */ - EM_ASM_({ - if (!window.clipboardData) return; - var contents = window.clipboardData.getData('Text'); - ccall('Window_GotClipboardText', 'void', ['string'], [contents]); - }); + EM_ASM_({ window.cc_copyText = UTF8ToString($0); }, str); } void Window_Show(void) { } diff --git a/src/Window.h b/src/Window.h index b59ed5e55..b60bc7cba 100644 --- a/src/Window.h +++ b/src/Window.h @@ -82,15 +82,14 @@ void Window_Create(int width, int height); /* Sets the text of the titlebar above the window. */ CC_API void Window_SetTitle(const cc_string* title); -typedef void (*RequestClipboardCallback)(cc_string* value, void* obj); /* Gets the text currently on the clipboard. */ +/* NOTE: On most platforms this function can be called at any time. */ +/* In web backend, can only be called during INPUT_CLIPBOARD_PASTE event. */ CC_API void Clipboard_GetText(cc_string* value); /* Sets the text currently on the clipboard. */ +/* NOTE: On most platforms this function can be called at any time. */ +/* In web backend, can only be called during INPUT_CLIPBOARD_COPY event. */ CC_API void Clipboard_SetText(const cc_string* value); -/* Calls a callback function when text is retrieved from the clipboard. */ -/* NOTE: On most platforms this just calls Clipboard_GetText. */ -/* With emscripten however, the callback is instead called when a 'paste' event arrives. */ -void Clipboard_RequestText(RequestClipboardCallback callback, void* obj); /* Makes the window visible and focussed on screen. */ void Window_Show(void);