Fixed bug 1573 - SDL does not support system clipboard on Android.
Philipp Wiesemann 2012-08-18 14:09:47 PDT
there is currently no way in SDL to interact with the system clipboard on
Android.
I attached a patch which tries to implement the three clipboard functions for
Android. It does not add the CLIPBOARDUPDATE event because this seems to
require Android API 11 or polling.
--- a/src/core/android/SDL_android.cpp Wed Sep 26 15:57:28 2012 -0300
+++ b/src/core/android/SDL_android.cpp Wed Sep 26 20:14:37 2012 -0700
@@ -735,6 +735,84 @@
return Android_JNI_FileClose(ctx, true);
}
+// returns a new global reference which needs to be released later
+static jobject Android_JNI_GetSystemServiceObject(const char* name)
+{
+ LocalReferenceHolder refs;
+ JNIEnv* env = Android_JNI_GetEnv();
+ if (!refs.init(env)) {
+ return NULL;
+ }
+
+ jstring service = env->NewStringUTF(name);
+
+ jmethodID mid;
+
+ mid = env->GetStaticMethodID(mActivityClass, "getContext", "()Landroid/content/Context;");
+ jobject context = env->CallStaticObjectMethod(mActivityClass, mid);
+
+ mid = env->GetMethodID(mActivityClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+ jobject manager = env->CallObjectMethod(context, mid, service);
+
+ env->DeleteLocalRef(service);
+
+ return manager ? env->NewGlobalRef(manager) : NULL;
+}
+
+#define SETUP_CLIPBOARD(error) \
+ LocalReferenceHolder refs; \
+ JNIEnv* env = Android_JNI_GetEnv(); \
+ if (!refs.init(env)) { \
+ return error; \
+ } \
+ jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
+ if (!clipboard) { \
+ return error; \
+ }
+
+extern "C" int Android_JNI_SetClipboardText(const char* text)
+{
+ SETUP_CLIPBOARD(-1)
+
+ jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "setText", "(Ljava/lang/CharSequence;)V");
+ jstring string = env->NewStringUTF(text);
+ env->CallVoidMethod(clipboard, mid, string);
+ env->DeleteGlobalRef(clipboard);
+ env->DeleteLocalRef(string);
+ return 0;
+}
+
+extern "C" char* Android_JNI_GetClipboardText()
+{
+ SETUP_CLIPBOARD(SDL_strdup(""))
+
+ jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "getText", "()Ljava/lang/CharSequence;");
+ jobject sequence = env->CallObjectMethod(clipboard, mid);
+ env->DeleteGlobalRef(clipboard);
+ if (sequence) {
+ mid = env->GetMethodID(env->GetObjectClass(sequence), "toString", "()Ljava/lang/String;");
+ jstring string = reinterpret_cast<jstring>(env->CallObjectMethod(sequence, mid));
+ const char* utf = env->GetStringUTFChars(string, 0);
+ if (utf) {
+ char* text = SDL_strdup(utf);
+ env->ReleaseStringUTFChars(string, utf);
+ return text;
+ }
+ }
+ return SDL_strdup("");
+}
+
+extern "C" SDL_bool Android_JNI_HasClipboardText()
+{
+ SETUP_CLIPBOARD(SDL_FALSE)
+
+ jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "hasText", "()Z");
+ jboolean has = env->CallBooleanMethod(clipboard, mid);
+ env->DeleteGlobalRef(clipboard);
+ return has ? SDL_TRUE : SDL_FALSE;
+}
+
+
// returns 0 on success or -1 on error (others undefined then)
// returns truthy or falsy value in plugged, charged and battery
// returns the value in seconds and percent or -1 if not available
--- a/src/core/android/SDL_android.h Wed Sep 26 15:57:28 2012 -0300
+++ b/src/core/android/SDL_android.h Wed Sep 26 20:14:37 2012 -0700
@@ -47,6 +47,11 @@
size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num);
int Android_JNI_FileClose(SDL_RWops* ctx);
+/* Clipboard support */
+int Android_JNI_SetClipboardText(const char* text);
+char* Android_JNI_GetClipboardText();
+SDL_bool Android_JNI_HasClipboardText();
+
/* Power support */
int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/android/SDL_androidclipboard.c Wed Sep 26 20:14:37 2012 -0700
@@ -0,0 +1,26 @@
+#include "SDL_config.h"
+
+#if SDL_VIDEO_DRIVER_ANDROID
+
+#include "SDL_androidvideo.h"
+
+#include "../../core/android/SDL_android.h"
+
+int
+Android_SetClipboardText(_THIS, const char *text)
+{
+ return Android_JNI_SetClipboardText(text);
+}
+
+char *
+Android_GetClipboardText(_THIS)
+{
+ return Android_JNI_GetClipboardText();
+}
+
+SDL_bool Android_HasClipboardText(_THIS)
+{
+ return Android_JNI_HasClipboardText();
+}
+
+#endif /* SDL_VIDEO_DRIVER_ANDROID */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/android/SDL_androidclipboard.h Wed Sep 26 20:14:37 2012 -0700
@@ -0,0 +1,10 @@
+#include "SDL_config.h"
+
+#ifndef _SDL_androidclipboard_h
+#define _SDL_androidclipboard_h
+
+extern int Android_SetClipboardText(_THIS, const char *text);
+extern char *Android_GetClipboardText(_THIS);
+extern SDL_bool Android_HasClipboardText(_THIS);
+
+#endif /* _SDL_androidclipboard_h */
--- a/src/video/android/SDL_androidvideo.c Wed Sep 26 15:57:28 2012 -0300
+++ b/src/video/android/SDL_androidvideo.c Wed Sep 26 20:14:37 2012 -0700
@@ -33,6 +33,7 @@
#include "../../events/SDL_windowevents_c.h"
#include "SDL_androidvideo.h"
+#include "SDL_androidclipboard.h"
#include "SDL_androidevents.h"
#include "SDL_androidkeyboard.h"
#include "SDL_androidwindow.h"
@@ -126,6 +127,11 @@
device->SDL_ToggleScreenKeyboard = Android_ToggleScreenKeyboard;
device->SDL_IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
+ /* Clipboard */
+ device->SetClipboardText = Android_SetClipboardText;
+ device->GetClipboardText = Android_GetClipboardText;
+ device->HasClipboardText = Android_HasClipboardText;
+
return device;
}