Fixed bug 1573 - SDL does not support system clipboard on Android.
authorSam Lantinga <slouken@libsdl.org>
Wed, 26 Sep 2012 20:14:37 -0700
changeset 6464ab55284b389f
parent 6463 051403ca44cc
child 6465 09b96f7ebe80
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.
src/core/android/SDL_android.cpp
src/core/android/SDL_android.h
src/video/android/SDL_androidclipboard.c
src/video/android/SDL_androidclipboard.h
src/video/android/SDL_androidvideo.c
     1.1 --- a/src/core/android/SDL_android.cpp	Wed Sep 26 15:57:28 2012 -0300
     1.2 +++ b/src/core/android/SDL_android.cpp	Wed Sep 26 20:14:37 2012 -0700
     1.3 @@ -735,6 +735,84 @@
     1.4      return Android_JNI_FileClose(ctx, true);
     1.5  }
     1.6  
     1.7 +// returns a new global reference which needs to be released later
     1.8 +static jobject Android_JNI_GetSystemServiceObject(const char* name)
     1.9 +{
    1.10 +    LocalReferenceHolder refs;
    1.11 +    JNIEnv* env = Android_JNI_GetEnv();
    1.12 +    if (!refs.init(env)) {
    1.13 +        return NULL;
    1.14 +    }
    1.15 +
    1.16 +    jstring service = env->NewStringUTF(name);
    1.17 +
    1.18 +    jmethodID mid;
    1.19 +
    1.20 +    mid = env->GetStaticMethodID(mActivityClass, "getContext", "()Landroid/content/Context;");
    1.21 +    jobject context = env->CallStaticObjectMethod(mActivityClass, mid);
    1.22 +
    1.23 +    mid = env->GetMethodID(mActivityClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
    1.24 +    jobject manager = env->CallObjectMethod(context, mid, service);
    1.25 +
    1.26 +    env->DeleteLocalRef(service);
    1.27 +
    1.28 +    return manager ? env->NewGlobalRef(manager) : NULL;
    1.29 +}
    1.30 +
    1.31 +#define SETUP_CLIPBOARD(error) \
    1.32 +    LocalReferenceHolder refs; \
    1.33 +    JNIEnv* env = Android_JNI_GetEnv(); \
    1.34 +    if (!refs.init(env)) { \
    1.35 +        return error; \
    1.36 +    } \
    1.37 +    jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
    1.38 +    if (!clipboard) { \
    1.39 +        return error; \
    1.40 +    }
    1.41 +
    1.42 +extern "C" int Android_JNI_SetClipboardText(const char* text)
    1.43 +{
    1.44 +    SETUP_CLIPBOARD(-1)
    1.45 +
    1.46 +    jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "setText", "(Ljava/lang/CharSequence;)V");
    1.47 +    jstring string = env->NewStringUTF(text);
    1.48 +    env->CallVoidMethod(clipboard, mid, string);
    1.49 +    env->DeleteGlobalRef(clipboard);
    1.50 +    env->DeleteLocalRef(string);
    1.51 +    return 0;
    1.52 +}
    1.53 +
    1.54 +extern "C" char* Android_JNI_GetClipboardText()
    1.55 +{
    1.56 +    SETUP_CLIPBOARD(SDL_strdup(""))
    1.57 +
    1.58 +    jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "getText", "()Ljava/lang/CharSequence;");
    1.59 +    jobject sequence = env->CallObjectMethod(clipboard, mid);
    1.60 +    env->DeleteGlobalRef(clipboard);
    1.61 +    if (sequence) {
    1.62 +        mid = env->GetMethodID(env->GetObjectClass(sequence), "toString", "()Ljava/lang/String;");
    1.63 +        jstring string = reinterpret_cast<jstring>(env->CallObjectMethod(sequence, mid));
    1.64 +        const char* utf = env->GetStringUTFChars(string, 0);
    1.65 +        if (utf) {
    1.66 +            char* text = SDL_strdup(utf);
    1.67 +            env->ReleaseStringUTFChars(string, utf);
    1.68 +            return text;
    1.69 +        }
    1.70 +    }
    1.71 +    return SDL_strdup("");
    1.72 +}
    1.73 +
    1.74 +extern "C" SDL_bool Android_JNI_HasClipboardText()
    1.75 +{
    1.76 +    SETUP_CLIPBOARD(SDL_FALSE)
    1.77 +
    1.78 +    jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "hasText", "()Z");
    1.79 +    jboolean has = env->CallBooleanMethod(clipboard, mid);
    1.80 +    env->DeleteGlobalRef(clipboard);
    1.81 +    return has ? SDL_TRUE : SDL_FALSE;
    1.82 +}
    1.83 +
    1.84 +
    1.85  // returns 0 on success or -1 on error (others undefined then)
    1.86  // returns truthy or falsy value in plugged, charged and battery
    1.87  // returns the value in seconds and percent or -1 if not available
     2.1 --- a/src/core/android/SDL_android.h	Wed Sep 26 15:57:28 2012 -0300
     2.2 +++ b/src/core/android/SDL_android.h	Wed Sep 26 20:14:37 2012 -0700
     2.3 @@ -47,6 +47,11 @@
     2.4  size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num);
     2.5  int Android_JNI_FileClose(SDL_RWops* ctx);
     2.6  
     2.7 +/* Clipboard support */
     2.8 +int Android_JNI_SetClipboardText(const char* text);
     2.9 +char* Android_JNI_GetClipboardText();
    2.10 +SDL_bool Android_JNI_HasClipboardText();
    2.11 +
    2.12  /* Power support */
    2.13  int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
    2.14  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/video/android/SDL_androidclipboard.c	Wed Sep 26 20:14:37 2012 -0700
     3.3 @@ -0,0 +1,26 @@
     3.4 +#include "SDL_config.h"
     3.5 +
     3.6 +#if SDL_VIDEO_DRIVER_ANDROID
     3.7 +
     3.8 +#include "SDL_androidvideo.h"
     3.9 +
    3.10 +#include "../../core/android/SDL_android.h"
    3.11 +
    3.12 +int
    3.13 +Android_SetClipboardText(_THIS, const char *text)
    3.14 +{
    3.15 +	return Android_JNI_SetClipboardText(text);
    3.16 +}
    3.17 +
    3.18 +char *
    3.19 +Android_GetClipboardText(_THIS)
    3.20 +{
    3.21 +	return Android_JNI_GetClipboardText();
    3.22 +}
    3.23 +
    3.24 +SDL_bool Android_HasClipboardText(_THIS)
    3.25 +{
    3.26 +	return Android_JNI_HasClipboardText();
    3.27 +}
    3.28 +
    3.29 +#endif /* SDL_VIDEO_DRIVER_ANDROID */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/video/android/SDL_androidclipboard.h	Wed Sep 26 20:14:37 2012 -0700
     4.3 @@ -0,0 +1,10 @@
     4.4 +#include "SDL_config.h"
     4.5 +
     4.6 +#ifndef _SDL_androidclipboard_h
     4.7 +#define _SDL_androidclipboard_h
     4.8 +
     4.9 +extern int Android_SetClipboardText(_THIS, const char *text);
    4.10 +extern char *Android_GetClipboardText(_THIS);
    4.11 +extern SDL_bool Android_HasClipboardText(_THIS);
    4.12 +
    4.13 +#endif /* _SDL_androidclipboard_h */
     5.1 --- a/src/video/android/SDL_androidvideo.c	Wed Sep 26 15:57:28 2012 -0300
     5.2 +++ b/src/video/android/SDL_androidvideo.c	Wed Sep 26 20:14:37 2012 -0700
     5.3 @@ -33,6 +33,7 @@
     5.4  #include "../../events/SDL_windowevents_c.h"
     5.5  
     5.6  #include "SDL_androidvideo.h"
     5.7 +#include "SDL_androidclipboard.h"
     5.8  #include "SDL_androidevents.h"
     5.9  #include "SDL_androidkeyboard.h"
    5.10  #include "SDL_androidwindow.h"
    5.11 @@ -126,6 +127,11 @@
    5.12      device->SDL_ToggleScreenKeyboard = Android_ToggleScreenKeyboard;
    5.13      device->SDL_IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
    5.14  
    5.15 +    /* Clipboard */
    5.16 +    device->SetClipboardText = Android_SetClipboardText;
    5.17 +    device->GetClipboardText = Android_GetClipboardText;
    5.18 +    device->HasClipboardText = Android_HasClipboardText;
    5.19 +
    5.20      return device;
    5.21  }
    5.22