From 16da838bda094c845f95521bc46a9648525c13ab Mon Sep 17 00:00:00 2001 From: pelya Date: Thu, 1 Jan 2015 04:43:30 +0200 Subject: [PATCH] Android 3.0 is now lowest supported version, because of new 'clipboard changed' notification in SDL_syswm.h, using SDL_SYSWMEVENT. --- project/AndroidManifestTemplate.xml | 2 +- project/java/Video.java | 23 +++++++- .../xserver/AndroidAppSettings.cfg | 4 +- .../jni/sdl-1.2/include/SDL_screenkeyboard.h | 24 +++++++++ project/jni/sdl-1.2/include/SDL_syswm.h | 25 ++++++++- .../src/video/android/SDL_androidinput.c | 9 ++++ .../src/video/android/SDL_androidvideo.c | 53 +++++++++++++++++-- readme.txt | 2 +- 8 files changed, 132 insertions(+), 10 deletions(-) diff --git a/project/AndroidManifestTemplate.xml b/project/AndroidManifestTemplate.xml index bafb14efe..830f508c5 100644 --- a/project/AndroidManifestTemplate.xml +++ b/project/AndroidManifestTemplate.xml @@ -31,7 +31,7 @@ - + diff --git a/project/java/Video.java b/project/java/Video.java index 3a600fb38..aa7dea466 100644 --- a/project/java/Video.java +++ b/project/java/Video.java @@ -57,7 +57,8 @@ import android.widget.TextView; import android.widget.Toast; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; -import android.text.ClipboardManager; +import android.content.ClipboardManager; +import android.content.ClipboardManager.OnPrimaryClipChangedListener; class Mouse @@ -570,7 +571,14 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer public DemoRenderer(MainActivity _context) { context = _context; - clipboard = (android.text.ClipboardManager) context.getSystemService(context.CLIPBOARD_SERVICE); + clipboard = (ClipboardManager) context.getSystemService(context.CLIPBOARD_SERVICE); + clipboard.addPrimaryClipChangedListener(new OnPrimaryClipChangedListener() + { + public void onPrimaryClipChanged() + { + nativeClipboardChanged(); + } + }); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { @@ -766,6 +774,16 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer return ret; } + public void setClipboardText(final String s) // Called from native code + { + try { + if( clipboard != null ) + clipboard.setText(s); + } catch (Exception e) { + Log.i("SDL", "setClipboardText() exception: " + e.toString()); + } + } + public void exitApp() { nativeDone(); @@ -920,6 +938,7 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer public native void nativeGlContextLostAsyncEvent(); public static native void nativeTextInput( int ascii, int unicode ); public static native void nativeTextInputFinished(); + public static native void nativeClipboardChanged(); private MainActivity context = null; public AccelerometerReader accelerometer = null; diff --git a/project/jni/application/xserver/AndroidAppSettings.cfg b/project/jni/application/xserver/AndroidAppSettings.cfg index 64fccf5ff..5bc76e329 100644 --- a/project/jni/application/xserver/AndroidAppSettings.cfg +++ b/project/jni/application/xserver/AndroidAppSettings.cfg @@ -7,10 +7,10 @@ AppName="XServer XSDL" AppFullName=x.org.server # Application version code (integer) -AppVersionCode=11119 +AppVersionCode=11120 # Application user-visible version name (string) -AppVersionName="1.11.19" +AppVersionName="1.11.20" # Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...' # If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu diff --git a/project/jni/sdl-1.2/include/SDL_screenkeyboard.h b/project/jni/sdl-1.2/include/SDL_screenkeyboard.h index 639efc02c..9b84914d6 100644 --- a/project/jni/sdl-1.2/include/SDL_screenkeyboard.h +++ b/project/jni/sdl-1.2/include/SDL_screenkeyboard.h @@ -148,6 +148,30 @@ extern DECLSPEC void SDLCALL SDL_ANDROID_SetGamepadKeymap(int A, int B, int X, i /* Copy contents of Android clipboard into supplied buffer */ extern DECLSPEC void SDLCALL SDL_ANDROID_GetClipboardText(char * buf, int len); +/* Copy of SDL2 API */ + +/** + * \brief Put UTF-8 text into the clipboard + * + * \sa SDL_GetClipboardText() + */ + +extern DECLSPEC int SDLCALL SDL_SetClipboardText(const char *text); + +/** + * \brief Get UTF-8 text from the clipboard, which must be freed with SDL_free() + * + * \sa SDL_SetClipboardText() + */ +extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void); + +/** + * \brief Returns a flag indicating whether the clipboard exists and contains a text string that is non-empty + * + * \sa SDL_GetClipboardText() + */ +extern DECLSPEC int SDLCALL SDL_HasClipboardText(void); + #ifdef __cplusplus } #endif diff --git a/project/jni/sdl-1.2/include/SDL_syswm.h b/project/jni/sdl-1.2/include/SDL_syswm.h index bba6404d4..3e97f04a1 100644 --- a/project/jni/sdl-1.2/include/SDL_syswm.h +++ b/project/jni/sdl-1.2/include/SDL_syswm.h @@ -181,9 +181,32 @@ typedef struct SDL_SysWMinfo { int data; } SDL_SysWMinfo; -#else +#elif defined(SDL_VIDEO_DRIVER_ANDROID) + +#include "SDL_video.h" + +typedef enum { + SDL_SYSWM_ANDROID_CLIPBOARD_CHANGED, /* Call SDL_GetClipboardText() after receiving this event */ + SDL_SYSWM_ANDROID_SCREEN_VISIBLE_RECT, +} SDL_SYSWM_TYPE; /** The generic custom event structure */ +struct SDL_SysWMmsg { + SDL_version version; + SDL_SYSWM_TYPE type; + union { + SDL_Rect screenVisibleRect; /* These are physical screen dimensions, as returned by SDL_ListModes(NULL, 0)[0], not values from SDL_SetVideoMode() */ + } event; +}; + +/** The generic custom window manager information structure */ +typedef struct SDL_SysWMinfo { + SDL_version version; + int data; +} SDL_SysWMinfo; + +#else + struct SDL_SysWMmsg { SDL_version version; int data; diff --git a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c index e382fd30b..8ee0f02d2 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c @@ -37,6 +37,7 @@ If you compile this code with SDL 1.3 or newer, or use in some other way, the li #include "SDL.h" #include "SDL_config.h" +#include "SDL_syswm.h" #include "SDL_version.h" #include "SDL_mutex.h" @@ -1654,6 +1655,14 @@ JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeScreenVisibleRect) (JNIEnv* env, jobjec // Move mouse by 1 pixel to force screen update SDL_GetMouseState( &x, &y ); SDL_ANDROID_MainThreadPushMouseMotion(x > 0 ? x-1 : 0, y); + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) + { + struct SDL_SysWMmsg wmmsg; + SDL_VERSION(&wmmsg.version); + wmmsg.type = SDL_SYSWM_ANDROID_SCREEN_VISIBLE_RECT; + wmmsg.event.screenVisibleRect = (SDL_Rect) {x, y, w, h}; + SDL_PrivateSysWMEvent(&wmmsg); + } } else return; diff --git a/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c b/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c index ea482089d..0f94915a1 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c @@ -43,6 +43,7 @@ If you compile this code with SDL 1.3 or newer, or use in some other way, the li #include "SDL_mutex.h" #include "SDL_thread.h" #include "SDL_android.h" +#include "SDL_syswm.h" #include "../SDL_sysvideo.h" #include "../SDL_pixels_c.h" #include "../../events/SDL_events_c.h" @@ -76,6 +77,7 @@ static jmethodID JavaIsScreenKeyboardShown = NULL; static jmethodID JavaSetScreenKeyboardHintMessage = NULL; static jmethodID JavaStartAccelerometerGyroscope = NULL; static jmethodID JavaGetClipboardText = NULL; +static jmethodID JavaSetClipboardText = NULL; static jmethodID JavaGetAdvertisementParams = NULL; static jmethodID JavaSetAdvertisementVisible = NULL; static jmethodID JavaSetAdvertisementPosition = NULL; @@ -345,6 +347,7 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeInitJavaCallbacks) ( JNIEnv* env, jobject t JavaSetScreenKeyboardHintMessage = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "setScreenKeyboardHintMessage", "(Ljava/lang/String;)V"); JavaStartAccelerometerGyroscope = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "startAccelerometerGyroscope", "(I)V"); JavaGetClipboardText = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "getClipboardText", "()Ljava/lang/String;"); + JavaSetClipboardText = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "setClipboardText", "(Ljava/lang/String;)V"); JavaGetAdvertisementParams = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "getAdvertisementParams", "([I)V"); JavaSetAdvertisementVisible = (*JavaEnv)->GetMethodID(JavaEnv, JavaRendererClass, "setAdvertisementVisible", "(I)V"); @@ -419,7 +422,25 @@ JAVA_EXPORT_NAME(Settings_nativeSetVideoDepth) (JNIEnv* env, jobject thiz, jint void SDLCALL SDL_ANDROID_GetClipboardText(char * buf, int len) { - buf[0] = 0; + char *c = SDL_GetClipboardText(); + strncpy(buf, c, len); + buf[len-1] = 0; + SDL_free(c); +} + +int SDLCALL SDL_SetClipboardText(const char *text) +{ + (*JavaEnv)->PushLocalFrame(JavaEnv, 1); + jstring s = (*JavaEnv)->NewStringUTF(JavaEnv, text); + (*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaSetClipboardText, s ); + if( s ) + (*JavaEnv)->DeleteLocalRef( JavaEnv, s ); + (*JavaEnv)->PopLocalFrame(JavaEnv, NULL); +} + +char * SDLCALL SDL_GetClipboardText(void) +{ + char *buf = NULL; (*JavaEnv)->PushLocalFrame( JavaEnv, 1 ); jstring s = (jstring) (*JavaEnv)->CallObjectMethod( JavaEnv, JavaRenderer, JavaGetClipboardText ); if( s ) @@ -427,13 +448,39 @@ void SDLCALL SDL_ANDROID_GetClipboardText(char * buf, int len) const char *c = (*JavaEnv)->GetStringUTFChars( JavaEnv, s, NULL ); if( c ) { - strncpy(buf, c, len); - buf[len-1] = 0; + int len = strlen(c); + buf = SDL_malloc(len + 1); + memcpy(buf, c, len + 1); (*JavaEnv)->ReleaseStringUTFChars( JavaEnv, s, c ); } (*JavaEnv)->DeleteLocalRef( JavaEnv, s ); } (*JavaEnv)->PopLocalFrame( JavaEnv, NULL ); + if (buf == NULL) + { + buf = SDL_malloc(1); + buf[0] = 0; + } + return buf; +} + +int SDLCALL SDL_HasClipboardText(void) +{ + char *c = SDL_GetClipboardText(); + int ret = c[0] != 0; + SDL_free(c); + return ret; +} + +JAVA_EXPORT_NAME(DemoRenderer_nativeClipboardChanged) ( JNIEnv* env, jobject thiz ) +{ + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) + { + SDL_SysWMmsg wmmsg; + SDL_VERSION(&wmmsg.version); + wmmsg.type = SDL_SYSWM_ANDROID_CLIPBOARD_CHANGED; + SDL_PrivateSysWMEvent(&wmmsg); + } } int SDLCALL SDL_ANDROID_GetAdvertisementParams(int * visible, SDL_Rect * position) diff --git a/readme.txt b/readme.txt index bc7a34e3c..7ac975635 100644 --- a/readme.txt +++ b/readme.txt @@ -14,7 +14,7 @@ Install latest Android SDK and NDK from http://developer.android.com/index.html You'll need to install Java Ant too. Since for building apk files some java classes are needed as well, it is recommended to install OpenJDK and its development files. (On RPM based distros usually called java-x.x.x-openjdk and java-x.x.x-openjdk-devel) -The application will run on Android OS 1.6 and above, but will use features from Android 4.4 if available. +The application will run on Android 3.0 and above, but will use features from Android 5.0 if available. The most supported environment for this port is Linux, MacOs should be okay too. If you're developing under Windows you'd better install Portable Ubuntu, to get proper Linux environment running inside Windows, then install Linux toolchain on it.