Added love.system.openURL (resolves issue #863)

This commit is contained in:
Alex Szpakowski
2014-03-31 16:13:05 -03:00
parent c985b1f2f7
commit 38497d23da
7 changed files with 132 additions and 4 deletions
@@ -272,6 +272,7 @@
FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0716E1578300074F42 /* SDL2.framework */; }; FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0716E1578300074F42 /* SDL2.framework */; };
FA9FC0B0173D6E3E005027FF /* wrap_Window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9FC0AE173D6E3E005027FF /* wrap_Window.cpp */; }; FA9FC0B0173D6E3E005027FF /* wrap_Window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9FC0AE173D6E3E005027FF /* wrap_Window.cpp */; };
FA9FC0B1173D6E3E005027FF /* wrap_Window.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9FC0AF173D6E3E005027FF /* wrap_Window.h */; }; FA9FC0B1173D6E3E005027FF /* wrap_Window.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9FC0AF173D6E3E005027FF /* wrap_Window.h */; };
FAA627CE18E7E1560080752D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAA627CD18E7E1560080752D /* CoreServices.framework */; };
FAAC6B02170A373B008A61C5 /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAAC6B00170A373A008A61C5 /* CompressedData.cpp */; }; FAAC6B02170A373B008A61C5 /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAAC6B00170A373A008A61C5 /* CompressedData.cpp */; };
FAAC6B03170A373B008A61C5 /* CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAC6B01170A373A008A61C5 /* CompressedData.h */; }; FAAC6B03170A373B008A61C5 /* CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAC6B01170A373A008A61C5 /* CompressedData.h */; };
FAAFF04416CB11C700CCDE45 /* OpenAL-Soft.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */; }; FAAFF04416CB11C700CCDE45 /* OpenAL-Soft.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */; };
@@ -831,6 +832,7 @@
FA9B4A0716E1578300074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = "<absolute>"; }; FA9B4A0716E1578300074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = "<absolute>"; };
FA9FC0AE173D6E3E005027FF /* wrap_Window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Window.cpp; sourceTree = "<group>"; }; FA9FC0AE173D6E3E005027FF /* wrap_Window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Window.cpp; sourceTree = "<group>"; };
FA9FC0AF173D6E3E005027FF /* wrap_Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Window.h; sourceTree = "<group>"; }; FA9FC0AF173D6E3E005027FF /* wrap_Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Window.h; sourceTree = "<group>"; };
FAA627CD18E7E1560080752D /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
FAAC6B00170A373A008A61C5 /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = "<group>"; }; FAAC6B00170A373A008A61C5 /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = "<group>"; };
FAAC6B01170A373A008A61C5 /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = "<group>"; }; FAAC6B01170A373A008A61C5 /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = "<group>"; };
FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "OpenAL-Soft.framework"; path = "/Library/Frameworks/OpenAL-Soft.framework"; sourceTree = "<absolute>"; }; FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "OpenAL-Soft.framework"; path = "/Library/Frameworks/OpenAL-Soft.framework"; sourceTree = "<absolute>"; };
@@ -895,6 +897,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
FAA627CE18E7E1560080752D /* CoreServices.framework in Frameworks */,
FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */, FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */,
FAAFF04416CB11C700CCDE45 /* OpenAL-Soft.framework in Frameworks */, FAAFF04416CB11C700CCDE45 /* OpenAL-Soft.framework in Frameworks */,
FA577AB016C7507900860150 /* Cocoa.framework in Frameworks */, FA577AB016C7507900860150 /* Cocoa.framework in Frameworks */,
@@ -1830,8 +1833,8 @@
FA577A6616C7199700860150 /* Frameworks */ = { FA577A6616C7199700860150 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA9B4A0716E1578300074F42 /* SDL2.framework */,
FA577A7916C71A1700860150 /* Cocoa.framework */, FA577A7916C71A1700860150 /* Cocoa.framework */,
FAA627CD18E7E1560080752D /* CoreServices.framework */,
FA577A6716C719D900860150 /* FreeType.framework */, FA577A6716C719D900860150 /* FreeType.framework */,
FA577A6916C719DE00860150 /* IL.framework */, FA577A6916C719DE00860150 /* IL.framework */,
FA577A8216C71A5300860150 /* libmodplug.framework */, FA577A8216C71A5300860150 /* libmodplug.framework */,
@@ -1841,6 +1844,7 @@
FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */, FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */,
FA577A7C16C71A2600860150 /* OpenGL.framework */, FA577A7C16C71A2600860150 /* OpenGL.framework */,
FA577A7316C719F900860150 /* physfs.framework */, FA577A7316C719F900860150 /* physfs.framework */,
FA9B4A0716E1578300074F42 /* SDL2.framework */,
FA577A7716C71A0800860150 /* Vorbis.framework */, FA577A7716C71A0800860150 /* Vorbis.framework */,
); );
name = Frameworks; name = Frameworks;
Regular → Executable
+21
View File
@@ -45,6 +45,27 @@ std::string to_utf8(LPCWSTR wstr)
return ret; return ret;
} }
std::wstring to_widestr(const std::string &str)
{
if (str.empty())
return std::wstring();
int wide_size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int) str.length(), nullptr, 0);
if (wide_size == 0)
return std::wstring();
std::wstring widestr;
widestr.resize(wide_size);
int ok = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int) str.length(), &widestr[0], widestr.length());
if (!ok)
return std::wstring();
return widestr;
}
void replace_char(std::string &str, char find, char replace) void replace_char(std::string &str, char find, char replace)
{ {
int length = str.length(); int length = str.length();
Regular → Executable
+7
View File
@@ -35,6 +35,13 @@ namespace love
**/ **/
std::string to_utf8(LPCWSTR wstr); std::string to_utf8(LPCWSTR wstr);
/**
* Convert a UTF-8 encoded string to a wide string.
* @param str The UTF-8 string.
* @return A wide string.
**/
std::wstring to_widestr(const std::string &str);
/** /**
* Replace all occurences of 'find' with 'replace' in a string. * Replace all occurences of 'find' with 'replace' in a string.
* @param str The string to modify. * @param str The string to modify.
Regular → Executable
+80 -3
View File
@@ -18,8 +18,22 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
// LOVE
#include "common/config.h"
#include "System.h" #include "System.h"
#if defined(LOVE_MACOSX)
#include <CoreServices/CoreServices.h>
#elif defined(LOVE_LINUX)
#include <stdlib.h>
#include <unistd.h>
#elif defined(LOVE_WINDOWS)
#include "common/utf8.h"
#include <shlobj.h>
#include <shellapi.h>
#pragma comment(lib, "shell32.lib")
#endif
namespace love namespace love
{ {
namespace system namespace system
@@ -27,17 +41,80 @@ namespace system
std::string System::getOS() const std::string System::getOS() const
{ {
#ifdef LOVE_MACOSX #if defined(LOVE_MACOSX)
return "OS X"; return "OS X";
#elif LOVE_WINDOWS #elif defined(LOVE_WINDOWS)
return "Windows"; return "Windows";
#elif LOVE_LINUX #elif defined(LOVE_LINUX)
return "Linux"; return "Linux";
#else #else
return "Unknown"; return "Unknown";
#endif #endif
} }
bool System::openURL(const std::string &url) const
{
bool success = false;
#if defined(LOVE_MACOSX)
// We could be lazy and use system("open " + url), but this is safer.
CFURLRef cfurl = CFURLCreateWithBytes(nullptr,
(const UInt8 *) url.c_str(),
url.length(),
kCFStringEncodingUTF8,
nullptr);
success = LSOpenCFURLRef(cfurl, nullptr) == noErr;
CFRelease(cfurl);
#elif defined(LOVE_LINUX)
// Spawn a child process, which we'll replace with xdg-open.
pid_t pid = vfork();
if (pid == 0) // Child process.
{
// Replace the child process with xdg-open and pass in the URL.
execlp("xdg-open", "xdg-open", url.c_str(), nullptr);
// exec will only return if it errored, so we should exit with non-zero.
_exit(1);
}
else if (pid > 0) // Parent process.
{
// Wait for xdg-open to complete (or fail.)
int status = 0;
if (waitpid(pid, &status, 0) == pid)
success = (status == 0);
else
success = false;
}
else
{
// vfork() failed.
success = false;
}
#elif defined(LOVE_WINDOWS)
// Unicode-aware WinAPI functions don't accept UTF-8, so we need to convert.
std::wstring wurl = to_widestr(url);
HINSTANCE result = ShellExecuteW(nullptr,
L"open",
wurl.c_str(),
nullptr,
nullptr,
SW_SHOW);
success = (int) result > 32;
#endif
return success;
}
bool System::getConstant(const char *in, System::PowerState &out) bool System::getConstant(const char *in, System::PowerState &out)
{ {
return powerStates.find(in, out); return powerStates.find(in, out);
+10
View File
@@ -85,6 +85,16 @@ public:
**/ **/
virtual PowerState getPowerInfo(int &seconds, int &percent) const = 0; virtual PowerState getPowerInfo(int &seconds, int &percent) const = 0;
/**
* Opens the specified URL with the user's default program to handle that
* particular URL type.
*
* @param url The URL to open.
*
* @return Whether the URL was opened successfully.
**/
virtual bool openURL(const std::string &url) const;
static bool getConstant(const char *in, PowerState &out); static bool getConstant(const char *in, PowerState &out);
static bool getConstant(PowerState in, const char *&out); static bool getConstant(PowerState in, const char *&out);
+8
View File
@@ -79,6 +79,13 @@ int w_getPowerInfo(lua_State *L)
return 3; return 3;
} }
int w_openURL(lua_State *L)
{
std::string url = luax_checkstring(L, 1);
luax_pushboolean(L, instance->openURL(url));
return 1;
}
static const luaL_Reg functions[] = static const luaL_Reg functions[] =
{ {
{ "getOS", w_getOS }, { "getOS", w_getOS },
@@ -86,6 +93,7 @@ static const luaL_Reg functions[] =
{ "setClipboardText", w_setClipboardText }, { "setClipboardText", w_setClipboardText },
{ "getClipboardText", w_getClipboardText }, { "getClipboardText", w_getClipboardText },
{ "getPowerInfo", w_getPowerInfo }, { "getPowerInfo", w_getPowerInfo },
{ "openURL", w_openURL },
{ 0, 0 } { 0, 0 }
}; };
+1
View File
@@ -35,6 +35,7 @@ int w_getProcessorCount(lua_State *L);
int w_setClipboardText(lua_State *L); int w_setClipboardText(lua_State *L);
int w_getClipboardText(lua_State *L); int w_getClipboardText(lua_State *L);
int w_getPowerInfo(lua_State *L); int w_getPowerInfo(lua_State *L);
int w_openURL(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_system(lua_State *L); extern "C" LOVE_EXPORT int luaopen_love_system(lua_State *L);
} // system } // system