diff --git a/imgui-binding/src/main/java/imgui/ImGui.java b/imgui-binding/src/main/java/imgui/ImGui.java index a5779a8..6cfb794 100644 --- a/imgui-binding/src/main/java/imgui/ImGui.java +++ b/imgui-binding/src/main/java/imgui/ImGui.java @@ -18,7 +18,7 @@ public final class ImGui { static { System.loadLibrary(System.getProperty(LIB_NAME_PROP, LIB_NAME_DEFAULT)); - initJniCommon(); + initJni(); ImDrawList.nInit(); ImDrawData.nInit(); nInitInputTextData(); @@ -31,10 +31,12 @@ public final class ImGui { #include #include #include "jni_common.h" + #include "jni_callbacks.h" */ - private static native void initJniCommon(); /* + private static native void initJni(); /* Jni::InitCommon(env); + Jni::InitCallbacks(env); */ // Context creation and access diff --git a/imgui-binding/src/main/java/imgui/ImGuiIO.java b/imgui-binding/src/main/java/imgui/ImGuiIO.java index d12bd26..bb9de4e 100644 --- a/imgui-binding/src/main/java/imgui/ImGuiIO.java +++ b/imgui-binding/src/main/java/imgui/ImGuiIO.java @@ -1,5 +1,8 @@ package imgui; +import imgui.callbacks.ImStrConsumer; +import imgui.callbacks.ImStrSupplier; + /** * Communicate most settings and inputs/outputs to Dear ImGui using this structure. * Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage. @@ -11,6 +14,7 @@ public final class ImGuiIO { /*JNI #include #include "jni_common.h" + #include "jni_callbacks.h" */ //------------------------------------------------------------------ @@ -253,7 +257,41 @@ public final class ImGuiIO { ImGui::GetIO().BackendRendererName = obj_backendRendererName == NULL ? NULL : (char*)env->GetStringUTFChars(obj_backendRendererName, JNI_FALSE); */ - // TODO clipboard callback + // Optional: Access OS clipboard + // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) + + /*JNI + jobject _setClipboardTextCallback = nullptr; + jobject _getClipboardTextCallback = nullptr; + + void setClipboardTextStub(void* userData, const char* text) { + Jni::CallImStrConsumer(Jni::GetEnv(), _setClipboardTextCallback, text); + } + + const char* getClipboardTextStub(void* user_data) { + JNIEnv* env = Jni::GetEnv(); + jstring jstr = Jni::CallImStrSupplier(env, _getClipboardTextCallback); + return env->GetStringUTFChars(jstr, 0); + } + */ + + public native void setSetClipboardTextFn(ImStrConsumer setClipboardTextCallback); /* + if (_setClipboardTextCallback != nullptr) { + env->DeleteGlobalRef(_setClipboardTextCallback); + } + + _setClipboardTextCallback = env->NewGlobalRef(setClipboardTextCallback); + ImGui::GetIO().SetClipboardTextFn = setClipboardTextStub; + */ + + public native void setGetClipboardTextFn(ImStrSupplier getClipboardTextCallback); /* + if (_getClipboardTextCallback != nullptr) { + env->DeleteGlobalRef(_getClipboardTextCallback); + } + + _getClipboardTextCallback = env->NewGlobalRef(getClipboardTextCallback); + ImGui::GetIO().GetClipboardTextFn = getClipboardTextStub; + */ //------------------------------------------------------------------ // Input - Fill before calling NewFrame() diff --git a/imgui-binding/src/main/java/imgui/callbacks/ImStrConsumer.java b/imgui-binding/src/main/java/imgui/callbacks/ImStrConsumer.java new file mode 100644 index 0000000..89042e8 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/callbacks/ImStrConsumer.java @@ -0,0 +1,11 @@ +package imgui.callbacks; + +import java.util.function.Consumer; + +/** + * Callback to supply Java string form native code. + */ +public abstract class ImStrConsumer implements Consumer { + @Override + public abstract void accept(String str); +} diff --git a/imgui-binding/src/main/java/imgui/callbacks/ImStrSupplier.java b/imgui-binding/src/main/java/imgui/callbacks/ImStrSupplier.java new file mode 100644 index 0000000..64781f1 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/callbacks/ImStrSupplier.java @@ -0,0 +1,11 @@ +package imgui.callbacks; + +import java.util.function.Supplier; + +/** + * Callback to get Java string from native code. + */ +public abstract class ImStrSupplier implements Supplier { + @Override + public abstract String get(); +} diff --git a/imgui-binding/src/main/native/jni_callbacks.cpp b/imgui-binding/src/main/native/jni_callbacks.cpp new file mode 100644 index 0000000..da41dba --- /dev/null +++ b/imgui-binding/src/main/native/jni_callbacks.cpp @@ -0,0 +1,23 @@ +#include "jni_callbacks.h" + +jmethodID jImStrConsumerAcceptMID; +jmethodID jImStrSupplierGetMID; + +namespace Jni +{ +void InitCallbacks(JNIEnv* env) { + jclass jImStrConsumer = env->FindClass("imgui/callbacks/ImStrConsumer"); + jImStrConsumerAcceptMID = env->GetMethodID(jImStrConsumer, "accept", "(Ljava/lang/String;)V"); + + jclass jImStrSupplier = env->FindClass("imgui/callbacks/ImStrSupplier"); + jImStrSupplierGetMID = env->GetMethodID(jImStrSupplier, "get", "()Ljava/lang/String;"); +} + +void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str) { + env->CallVoidMethod(consumer, jImStrConsumerAcceptMID, env->NewStringUTF(str)); +} + +jstring CallImStrSupplier(JNIEnv* env, jobject supplier) { + return (jstring)env->CallObjectMethod(supplier, jImStrSupplierGetMID); +} +} diff --git a/imgui-binding/src/main/native/jni_callbacks.h b/imgui-binding/src/main/native/jni_callbacks.h new file mode 100644 index 0000000..a85caac --- /dev/null +++ b/imgui-binding/src/main/native/jni_callbacks.h @@ -0,0 +1,14 @@ +#include + +#ifndef JNI_CALLBACK_H +#define JNI_CALLBACK_H + +namespace Jni +{ +void InitCallbacks(JNIEnv* env); + +void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str); +jstring CallImStrSupplier(JNIEnv* env, jobject supplier); +} + +#endif diff --git a/imgui-binding/src/main/native/jni_common.cpp b/imgui-binding/src/main/native/jni_common.cpp index 85b3955..b2e8599 100644 --- a/imgui-binding/src/main/native/jni_common.cpp +++ b/imgui-binding/src/main/native/jni_common.cpp @@ -8,9 +8,13 @@ jfieldID imVec4YID; jfieldID imVec4ZID; jfieldID imVec4WID; +static JavaVM* jvm; + namespace Jni { void InitCommon(JNIEnv* env) { + env->GetJavaVM(&jvm); + jclass jImVec2Class = env->FindClass("imgui/ImVec2"); imVec2XID = env->GetFieldID(jImVec2Class, "x", "F"); imVec2YID = env->GetFieldID(jImVec2Class, "y", "F"); @@ -22,6 +26,13 @@ void InitCommon(JNIEnv* env) { imVec4WID = env->GetFieldID(jImVec4Class, "w", "F"); } +JNIEnv* GetEnv() { + JNIEnv* env; + jint res = jvm->GetEnv((void**)(&env), JNI_VERSION_1_8); + assert(res == JNI_OK); + return env; +} + void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst) { env->SetFloatField(dst, imVec2XID, src->x); env->SetFloatField(dst, imVec2YID, src->y); diff --git a/imgui-binding/src/main/native/jni_common.h b/imgui-binding/src/main/native/jni_common.h index 2816f0a..63150e3 100644 --- a/imgui-binding/src/main/native/jni_common.h +++ b/imgui-binding/src/main/native/jni_common.h @@ -8,6 +8,8 @@ namespace Jni { void InitCommon(JNIEnv* env); +JNIEnv* GetEnv(); + void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst); void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst); diff --git a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java index 27f81e2..5cd85ff 100644 --- a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java +++ b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java @@ -2,6 +2,8 @@ import imgui.ImBool; import imgui.ImGui; import imgui.ImGuiIO; import imgui.ImString; +import imgui.callbacks.ImStrConsumer; +import imgui.callbacks.ImStrSupplier; import imgui.enums.ImGuiBackendFlags; import imgui.enums.ImGuiColorEditFlags; import imgui.enums.ImGuiCond; @@ -214,6 +216,20 @@ public final class ImGuiGlfwExample { io.setMouseWheel(io.getMouseWheel() + (float) yOffset); }); + io.setSetClipboardTextFn(new ImStrConsumer() { + @Override + public void accept(final String s) { + glfwSetClipboardString(window, s); + } + }); + + io.setGetClipboardTextFn(new ImStrSupplier() { + @Override + public String get() { + return glfwGetClipboardString(window); + } + }); + // Initialize renderer itself imGuiGl3.init(); }