diff -r 01966f6feadc android-project/src/org/libsdl/app/SDLActivity.java --- a/android-project/src/org/libsdl/app/SDLActivity.java Thu Jan 29 13:33:53 2015 -0800 +++ b/android-project/src/org/libsdl/app/SDLActivity.java Thu Feb 12 08:31:53 2015 +0100 @@ -27,6 +27,8 @@ import android.graphics.drawable.Drawable; import android.media.*; import android.hardware.*; +import android.content.Intent; +import android.net.Uri; /** SDL Activity @@ -433,6 +435,21 @@ /** * This method is called by SDL using JNI. */ + public static int openURL(String url) + { + try { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse(url)); + mSingleton.startActivity(i); + } catch (Exception ex) { + return -1; + } + return 0; + } + + /** + * This method is called by SDL using JNI. + */ public static boolean sendMessage(int command, int param) { return mSingleton.sendCommand(command, Integer.valueOf(param)); } diff -r 01966f6feadc include/SDL_filesystem.h --- a/include/SDL_filesystem.h Thu Jan 29 13:33:53 2015 -0800 +++ b/include/SDL_filesystem.h Thu Feb 12 08:31:53 2015 +0100 @@ -125,6 +125,15 @@ */ extern DECLSPEC char *SDLCALL SDL_GetPrefPath(const char *org, const char *app); +/** + * \brief Open an URL in a web browser + * + * \param url The URL to open (ex: "http://www.libsdl.org") + * + * \return 0 on success, -1 on error + */ +extern DECLSPEC int SDLCALL SDL_OpenURL(const char *url); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff -r 01966f6feadc src/core/android/SDL_android.c --- a/src/core/android/SDL_android.c Thu Jan 29 13:33:53 2015 -0800 +++ b/src/core/android/SDL_android.c Thu Feb 12 08:31:53 2015 +0100 @@ -477,6 +477,21 @@ } } +int Android_JNI_OpenURL(const char *url) +{ + int retval = -1; + jmethodID mid; + JNIEnv *mEnv = Android_JNI_GetEnv(); + mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,"openURL","(Ljava/lang/String;)I"); + if (mid) { + jstring jurl = (jstring)((*mEnv)->NewStringUTF(mEnv, url)); + retval = (*mEnv)->CallStaticIntMethod(mEnv, mActivityClass, mid, jurl); + (*mEnv)->DeleteLocalRef(mEnv, jurl); + } + + return retval; +} + SDL_bool Android_JNI_GetAccelerometerValues(float values[3]) { int i; diff -r 01966f6feadc src/core/android/SDL_android.h --- a/src/core/android/SDL_android.h Thu Jan 29 13:33:53 2015 -0800 +++ b/src/core/android/SDL_android.h Thu Feb 12 08:31:53 2015 +0100 @@ -37,6 +37,8 @@ extern SDL_bool Android_JNI_DeleteContext(void); */ extern void Android_JNI_SwapWindow(); extern void Android_JNI_SetActivityTitle(const char *title); +extern int Android_JNI_OpenURL(const char *url); + extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]); extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect); extern void Android_JNI_HideTextInput(); diff -r 01966f6feadc src/dynapi/SDL_dynapi_overrides.h --- a/src/dynapi/SDL_dynapi_overrides.h Thu Jan 29 13:33:53 2015 -0800 +++ b/src/dynapi/SDL_dynapi_overrides.h Thu Feb 12 08:31:53 2015 +0100 @@ -138,6 +138,7 @@ #define SDL_RegisterEvents SDL_RegisterEvents_REAL #define SDL_GetBasePath SDL_GetBasePath_REAL #define SDL_GetPrefPath SDL_GetPrefPath_REAL +#define SDL_OpenURL SDL_OpenURL_REAL #define SDL_GameControllerAddMapping SDL_GameControllerAddMapping_REAL #define SDL_GameControllerMappingForGUID SDL_GameControllerMappingForGUID_REAL #define SDL_GameControllerMapping SDL_GameControllerMapping_REAL diff -r 01966f6feadc src/dynapi/SDL_dynapi_procs.h --- a/src/dynapi/SDL_dynapi_procs.h Thu Jan 29 13:33:53 2015 -0800 +++ b/src/dynapi/SDL_dynapi_procs.h Thu Feb 12 08:31:53 2015 +0100 @@ -167,6 +167,7 @@ SDL_DYNAPI_PROC(Uint32,SDL_RegisterEvents,(int a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GetBasePath,(void),(),return) SDL_DYNAPI_PROC(char*,SDL_GetPrefPath,(const char *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_OpenURL,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GameControllerAddMapping,(const char *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GameControllerMappingForGUID,(SDL_JoystickGUID a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GameControllerMapping,(SDL_GameController *a),(a),return) diff -r 01966f6feadc src/filesystem/android/SDL_sysfilesystem.c --- a/src/filesystem/android/SDL_sysfilesystem.c Thu Jan 29 13:33:53 2015 -0800 +++ b/src/filesystem/android/SDL_sysfilesystem.c Thu Feb 12 08:31:53 2015 +0100 @@ -57,6 +57,16 @@ return NULL; } +int +SDL_OpenURL(const char *url) +{ + if (url == NULL) { + return SDL_InvalidParamError("url"); + } + + return Android_JNI_OpenURL(url); +} + #endif /* SDL_FILESYSTEM_ANDROID */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 01966f6feadc src/filesystem/cocoa/SDL_sysfilesystem.m --- a/src/filesystem/cocoa/SDL_sysfilesystem.m Thu Jan 29 13:33:53 2015 -0800 +++ b/src/filesystem/cocoa/SDL_sysfilesystem.m Thu Feb 12 08:31:53 2015 +0100 @@ -26,6 +26,7 @@ /* System dependent filesystem routines */ #include +#include #include #include @@ -98,6 +99,26 @@ return retval; }} +int +SDL_OpenURL(const char *url) +{ @autoreleasepool +{ + if (url == NULL) { + return SDL_InvalidParamError("url"); + } + + NSString *nsstr = [NSString stringWithUTF8String:url]; + NSURL *nsurl = [NSURL URLWithString:nsstr]; + bool retval; + + retval = [[NSWorkspace sharedWorkspace] openURL:nsurl]; + if (retval) { + return 0; + } else { + return -1; + } +}} + #endif /* SDL_FILESYSTEM_COCOA */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 01966f6feadc src/filesystem/unix/SDL_sysfilesystem.c --- a/src/filesystem/unix/SDL_sysfilesystem.c Thu Jan 29 13:33:53 2015 -0800 +++ b/src/filesystem/unix/SDL_sysfilesystem.c Thu Feb 12 08:31:53 2015 +0100 @@ -31,6 +31,7 @@ #include #include #include +#include #include #ifdef __FREEBSD__ @@ -205,6 +206,60 @@ return retval; } +int +SDL_OpenURL(const char *url) +{ + pid_t pid1; + int status; + + if (url == NULL) { + return SDL_InvalidParamError("url"); + } + + // Usual fork. (cannot use "vfork()" here, because after we will use "vfork()" which is + // different from "_exit()" and "exec*()" that are the only allowed functions). + pid1 = fork(); + if (pid1 == 0) { + // Child process + + // **************************************** + // Notice this is "vfork()" and not "fork()" + // See restrictions in documentation + // **************************************** + pid_t pid2 = vfork(); + if (pid2 == 0) { + // Grand child process will try to launch the url + execlp("xdg-open", "xdg-open", url, (char *)0); + _exit(EXIT_FAILURE); + } else if (pid2 < 0) { + // Error forking + _exit(EXIT_FAILURE); + } else { + // Child process doesn't wait for Grand child process which *might* be blocking. + // Success forking + _exit(EXIT_SUCCESS); + } + } else if (pid1 < 0) { + return -1; // Error forking + } else { + if (waitpid(pid1, &status, 0) == pid1) { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) { + return 0; // Sucess + } else { + return -1; // Error xdg-open + } + } else { + return -1; // Error in Child process + } + } else { + return -1; // Error waiting for Child process + } + } + + return 0; +} + #endif /* SDL_FILESYSTEM_UNIX */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 01966f6feadc src/power/uikit/SDL_syspower.m --- a/src/power/uikit/SDL_syspower.m Thu Jan 29 13:33:53 2015 -0800 +++ b/src/power/uikit/SDL_syspower.m Thu Feb 12 08:31:53 2015 +0100 @@ -91,6 +91,25 @@ return SDL_TRUE; /* always the definitive answer on iOS. */ } + +int SDL_OpenURL(const char *url) +{ + if (url == NULL) { + return SDL_InvalidParamError("url"); + } + + NSString *nsstr = [NSString stringWithUTF8String:url]; + NSURL *nsurl = [NSURL URLWithString:nsstr]; + bool retval; + + retval = [[UIApplication sharedApplication] openURL:nsurl]; + if (retval) { + return 0; + } else { + return -1; + } +} + #endif /* SDL_POWER_UIKIT */ #endif /* SDL_POWER_DISABLED */