15#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
16#define HAS_XDG_OPEN_HELPER
19#if defined(HAS_XDG_OPEN_HELPER)
23#include <sys/resource.h>
34#if defined(__FreeBSD__) || defined(__OpenBSD__)
41const char* ENV_PREFIX =
"APPIMAGE_PRESERVED_";
43bool IsPreservedEnvVar(
const char* var)
45 return strncmp(var, ENV_PREFIX, strlen(ENV_PREFIX)) == 0;
50 for(
auto envIterator = environ; *envIterator; ++envIterator)
52 auto envVar = *envIterator;
54 if (!IsPreservedEnvVar(envVar))
57 auto separator = strchr(envVar,
'=');
63 auto varName = std::string(envVar + strlen(ENV_PREFIX), separator);
68 auto varValue = separator + 1;
70 const auto result = *varValue ?
71 setenv(varName.c_str(), varValue,
true) :
72 unsetenv(varName.c_str());
81std::string FindXDGOpen()
83 const char *path = getenv(
"PATH");
91 const char *colon = strchr(path,
':');
93 colon = path + strlen(path);
95 result.assign(path, colon);
96 result +=
"/xdg-open";
98 if (access(result.c_str(), X_OK) == 0)
110bool RunXDGOpen(
const std::string& uri)
112 std::string xdgOpen = FindXDGOpen();
126 int secondFork = fork();
134 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
136 for (
int fd = STDERR_FILENO + 1; fd < rlim.rlim_cur; ++fd)
141 int fd = open(
"/dev/null", O_RDWR);
145 dup2(fd, STDIN_FILENO);
146 dup2(fd, STDOUT_FILENO);
147 dup2(fd, STDERR_FILENO);
149 if (fd > STDERR_FILENO)
156 char*
const args[] = {
157 const_cast<char*
>(xdgOpen.c_str()),
158 const_cast<char*
>(uri.c_str()),
162 execv(xdgOpen.c_str(), args);
176 waitpid(pid, &status, 0);
178 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
192WindowPlacement::operator bool()
const {
return false; }
217 p->DoCallAfter(action);
221 sActions.emplace_back(std::move(action));
231 std::vector<Action> actions;
233 for (
auto &action : actions)
248#if defined(HAS_XDG_OPEN_HELPER)
249 if (RunXDGOpen(url.ToStdString()))
254 return p->DoOpenInDefaultBrowser(url);
261 return XO(
"Message");
Toolkit-neutral facade for basic user interface services.
virtual ~GenericProgressDialog()
virtual ~ProgressDialog()
Abstract class defines a few user interface services, not mentioning particular toolkits.
virtual ~WindowPlacement()
Holds a msgid for the translation catalog; may also bind format arguments.
static Services * theInstance
TranslatableString DefaultCaption()
"Message", suitably translated
bool OpenInDefaultBrowser(const wxString &url)
Open an URL in default browser.
Services * Install(Services *pInstance)
Install an implementation; return the previously installed instance.
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
static std::vector< Action > sActions
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
std::function< void()> Action
static std::recursive_mutex sActionsMutex
void Yield()
Dispatch waiting events, including actions enqueued by CallAfter.