summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2019-12-02 17:56:31 +0100
committerGitHub <noreply@github.com>2019-12-02 17:56:31 +0100
commitcaea66533e96dd85d46086e4c3455d01a698aad3 (patch)
tree9fc672ecd3d8478dfd30e162aa0952fcce08d2a7 /util
parentc3020f9876a96044ad6c8ef43884c03e460159a8 (diff)
Initial clipboard support (#237)
* WIP clipboard support code dump. HTML5 clipboard/permissions API is a mess, so that's not an option. * sokol_app.h: clipboard on emscripten working * sokol_imgui.h: init-flag to disable Ctrl-hotkeys * sokol_app.h: new sapp_consume_event() function, rename clipboard event * add some todos to sokol_app.h * macOS: send CLIPBOARD_PASTED event * sokol_app.h: add Win32 clipboard support * sokol_app.h: documentation for clipboard support * sokol_app.h: dummy clipboard support * Start adding clipboard support to sokol_imgui. Current problem: on HTML5, copy/paste must happen inside JS event handler. * mention new sokol_app.h clipboard support in README * readme tweaks * sokol_app.h: MSVC warnings fixed * sokol_imgui.h: fix key debuffering * sokol_app.h: documentation fixes
Diffstat (limited to 'util')
-rw-r--r--util/sokol_imgui.h135
1 files changed, 121 insertions, 14 deletions
diff --git a/util/sokol_imgui.h b/util/sokol_imgui.h
index 7e796172..d8b3d8c7 100644
--- a/util/sokol_imgui.h
+++ b/util/sokol_imgui.h
@@ -219,6 +219,7 @@ typedef struct simgui_desc_t {
float dpi_scale;
const char* ini_filename;
bool no_default_font;
+ bool disable_hotkeys; /* don't let ImGui handle Ctrl-A,C,V,X,Y,Z */
} simgui_desc_t;
SOKOL_API_DECL void simgui_setup(const simgui_desc_t* desc);
@@ -251,6 +252,10 @@ SOKOL_API_DECL void simgui_shutdown(void);
#include <stddef.h> /* offsetof */
#include <string.h> /* memset */
+#if !defined(SOKOL_IMGUI_NO_SOKOL_APP) && defined(__EMSCRIPTEN__)
+#include <emscripten.h>
+#endif
+
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
@@ -278,6 +283,8 @@ typedef struct {
ImVec2 disp_size;
} _simgui_vs_params_t;
+#define SIMGUI_MAX_KEY_VALUE (512) // same as ImGuis IO.KeysDown array
+
typedef struct {
simgui_desc_t desc;
sg_buffer vbuf;
@@ -288,6 +295,9 @@ typedef struct {
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
bool btn_down[SAPP_MAX_MOUSEBUTTONS];
bool btn_up[SAPP_MAX_MOUSEBUTTONS];
+ uint8_t keys_down[SIMGUI_MAX_KEY_VALUE]; // bits 0..3 or modifiers, != 0 is key-down
+ uint8_t keys_up[SIMGUI_MAX_KEY_VALUE]; // same is keys_down
+ bool is_osx; // return true if running on OSX (or HTML5 OSX), needed for copy/paste
#endif
} _simgui_state_t;
static _simgui_state_t _simgui;
@@ -701,12 +711,46 @@ static const uint8_t _simgui_fs_bin[] = {
#error "sokol_imgui.h: No sokol_gfx.h backend selected (SOKOL_GLCORE33, SOKOL_GLES2, SOKOL_GLES3, SOKOL_D3D11 or SOKOL_METAL)"
#endif
+#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
+static void _simgui_set_clipboard(void* user_data, const char* text) {
+ sapp_set_clipboard_string(text);
+}
+
+static const char* _simgui_get_clipboard(void* user_data) {
+ return sapp_get_clipboard_string();
+}
+
+#if defined(__EMSCRIPTEN__)
+EM_JS(int, simgui_js_is_osx, (void), {
+ if (navigator.userAgent.includes('Macintosh')) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+});
+#endif
+
+static bool _simgui_is_osx(void) {
+ #if defined(__EMSCRIPTEN__)
+ return simgui_js_is_osx();
+ #elif defined(__APPLE__)
+ return true;
+ #else
+ return false;
+ #endif
+}
+#endif
+
SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
SOKOL_ASSERT(desc);
memset(&_simgui, 0, sizeof(_simgui));
_simgui.desc = *desc;
_simgui.desc.max_vertices = _simgui_def(_simgui.desc.max_vertices, 65536);
_simgui.desc.dpi_scale = _simgui_def(_simgui.desc.dpi_scale, 1.0f);
+ #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
+ _simgui.is_osx = _simgui_is_osx();
+ #endif
/* can keep color_format, depth_format and sample_count as is,
since sokol_gfx.h will do its own default-value handling
*/
@@ -728,6 +772,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
}
#endif
io->IniFilename = _simgui.desc.ini_filename;
+ io->ConfigMacOSXBehaviors = _simgui_is_osx();
io->BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
io->KeyMap[ImGuiKey_Tab] = SAPP_KEYCODE_TAB;
@@ -744,12 +789,18 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
io->KeyMap[ImGuiKey_Space] = SAPP_KEYCODE_SPACE;
io->KeyMap[ImGuiKey_Enter] = SAPP_KEYCODE_ENTER;
io->KeyMap[ImGuiKey_Escape] = SAPP_KEYCODE_ESCAPE;
- io->KeyMap[ImGuiKey_A] = SAPP_KEYCODE_A;
- io->KeyMap[ImGuiKey_C] = SAPP_KEYCODE_C;
- io->KeyMap[ImGuiKey_V] = SAPP_KEYCODE_V;
- io->KeyMap[ImGuiKey_X] = SAPP_KEYCODE_X;
- io->KeyMap[ImGuiKey_Y] = SAPP_KEYCODE_Y;
- io->KeyMap[ImGuiKey_Z] = SAPP_KEYCODE_Z;
+ if (!_simgui.desc.disable_hotkeys) {
+ io->KeyMap[ImGuiKey_A] = SAPP_KEYCODE_A;
+ io->KeyMap[ImGuiKey_C] = SAPP_KEYCODE_C;
+ io->KeyMap[ImGuiKey_V] = SAPP_KEYCODE_V;
+ io->KeyMap[ImGuiKey_X] = SAPP_KEYCODE_X;
+ io->KeyMap[ImGuiKey_Y] = SAPP_KEYCODE_Y;
+ io->KeyMap[ImGuiKey_Z] = SAPP_KEYCODE_Z;
+ }
+ #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
+ io->SetClipboardTextFn = _simgui_set_clipboard;
+ io->GetClipboardTextFn = _simgui_get_clipboard;
+ #endif
#endif
/* create sokol-gfx resources */
@@ -872,6 +923,13 @@ SOKOL_API_IMPL void simgui_shutdown(void) {
sg_destroy_buffer(_simgui.vbuf);
}
+_SOKOL_PRIVATE void _simgui_set_imgui_modifiers(ImGuiIO* io, uint8_t mods) {
+ io->KeyAlt = (mods & SAPP_MODIFIER_ALT) != 0;
+ io->KeyCtrl = (mods & SAPP_MODIFIER_CTRL) != 0;
+ io->KeyShift = (mods & SAPP_MODIFIER_SHIFT) != 0;
+ io->KeySuper = (mods & SAPP_MODIFIER_SUPER) != 0;
+}
+
SOKOL_API_IMPL void simgui_new_frame(int width, int height, double delta_time) {
#if defined(__cplusplus)
ImGuiIO* io = &ImGui::GetIO();
@@ -892,6 +950,18 @@ SOKOL_API_IMPL void simgui_new_frame(int width, int height, double delta_time) {
io->MouseDown[i] = false;
}
}
+ for (int i = 0; i < SIMGUI_MAX_KEY_VALUE; i++) {
+ if (_simgui.keys_down[i]) {
+ io->KeysDown[i] = true;
+ _simgui_set_imgui_modifiers(io, _simgui.keys_down[i]);
+ _simgui.keys_down[i] = 0;
+ }
+ else if (_simgui.keys_up[i]) {
+ io->KeysDown[i] = false;
+ _simgui_set_imgui_modifiers(io, _simgui.keys_up[i]);
+ _simgui.keys_up[i] = 0;
+ }
+ }
if (io->WantTextInput && !sapp_keyboard_shown()) {
sapp_show_keyboard(true);
}
@@ -1009,6 +1079,15 @@ SOKOL_API_IMPL void simgui_render(void) {
}
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
+_SOKOL_PRIVATE bool _simgui_is_ctrl(uint8_t modifiers) {
+ if (_simgui.is_osx) {
+ return 0 != (modifiers & SAPP_MODIFIER_SUPER);
+ }
+ else {
+ return 0 != (modifiers & SAPP_MODIFIER_CTRL);
+ }
+}
+
SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
const float dpi_scale = _simgui.desc.dpi_scale;
#if defined(__cplusplus)
@@ -1016,10 +1095,7 @@ SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
#else
ImGuiIO* io = igGetIO();
#endif
- io->KeyAlt = (ev->modifiers & SAPP_MODIFIER_ALT) != 0;
- io->KeyCtrl = (ev->modifiers & SAPP_MODIFIER_CTRL) != 0;
- io->KeyShift = (ev->modifiers & SAPP_MODIFIER_SHIFT) != 0;
- io->KeySuper = (ev->modifiers & SAPP_MODIFIER_SUPER) != 0;
+ _simgui_set_imgui_modifiers(io, ev->modifiers);
switch (ev->type) {
case SAPP_EVENTTYPE_MOUSE_DOWN:
io->MousePos.x = ev->mouse_x / dpi_scale;
@@ -1069,17 +1145,43 @@ SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
_simgui.btn_up[0] = _simgui.btn_down[0] = false;
break;
case SAPP_EVENTTYPE_KEY_DOWN:
- io->KeysDown[ev->key_code] = true;
+ /* intercept Ctrl-V, this is handled via EVENTTYPE_CLIPBOARD_PASTED */
+ if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_V)) {
+ break;
+ }
+ /* on web platform, don't forward Ctrl-X, Ctrl-V to the browser */
+ if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_X)) {
+ sapp_consume_event();
+ }
+ if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_C)) {
+ sapp_consume_event();
+ }
+ _simgui.keys_down[ev->key_code] = 0x80 | ev->modifiers;
break;
case SAPP_EVENTTYPE_KEY_UP:
- io->KeysDown[ev->key_code] = false;
+ /* intercept Ctrl-V, this is handled via EVENTTYPE_CLIPBOARD_PASTED */
+ if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_V)) {
+ break;
+ }
+ /* on web platform, don't forward Ctrl-X, Ctrl-V to the browser */
+ if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_X)) {
+ sapp_consume_event();
+ }
+ if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_C)) {
+ sapp_consume_event();
+ }
+ _simgui.keys_up[ev->key_code] = 0x80 | ev->modifiers;
break;
case SAPP_EVENTTYPE_CHAR:
/* on some platforms, special keys may be reported as
characters, which may confuse some ImGui widgets,
- drop those
+ drop those, also don't forward characters if some
+ modifiers have been pressed
*/
- if ((ev->char_code >= 32) && (ev->char_code != 127)) {
+ if ((ev->char_code >= 32) &&
+ (ev->char_code != 127) &&
+ (0 == (ev->modifiers & (SAPP_MODIFIER_ALT|SAPP_MODIFIER_CTRL|SAPP_MODIFIER_SUPER))))
+ {
#if defined(__cplusplus)
io->AddInputCharacter((ImWchar)ev->char_code);
#else
@@ -1087,6 +1189,11 @@ SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
#endif
}
break;
+ case SAPP_EVENTTYPE_CLIPBOARD_PASTED:
+ /* simulate a Ctrl-V key down/up */
+ _simgui.keys_down[SAPP_KEYCODE_V] = _simgui.keys_up[SAPP_KEYCODE_V] =
+ 0x80 | (_simgui.is_osx ? SAPP_MODIFIER_SUPER:SAPP_MODIFIER_CTRL);
+ break;
default:
break;
}