The Battle for Wesnoth  1.15.0-dev
open.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 - 2018 by Iris Morelle <shadowm2006@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "desktop/open.hpp"
16 
17 #include "log.hpp"
19 
20 #if defined(_X11) || defined(__APPLE__)
21 
22 #include <thread>
23 
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <unistd.h> // fork(), exec family
27 
28 #elif defined(_WIN32)
29 
30 #ifndef UNICODE
31 #define UNICODE
32 #endif
33 #define WIN32_LEAN_AND_MEAN
34 
35 #include <windows.h>
36 #include <shellapi.h> // ShellExecute()
37 
38 #endif
39 
40 static lg::log_domain log_desktop("desktop");
41 #define ERR_DU LOG_STREAM(err, log_desktop)
42 #define LOG_DU LOG_STREAM(info, log_desktop)
43 
44 namespace desktop {
45 
47 {
48 #if defined(_X11) || defined(__APPLE__) || defined(_WIN32)
49  return true;
50 #else
51  return false;
52 #endif
53 }
54 
55 bool open_object(const std::string& path_or_url)
56 {
57  LOG_DU << "open_object(): requested object: " << path_or_url << '\n';
58 
59 #if defined(_X11) || defined(__APPLE__)
60 
61 #ifndef __APPLE__
62  LOG_DU << "open_object(): on X11, will use xdg-open\n";
63  const char launcher[] = "xdg-open";
64 #else
65  LOG_DU << "open_object(): on OS X, will use open\n";
66  const char launcher[] = "open";
67 #endif
68 
69  const pid_t child = fork();
70 
71  if(child == -1) {
72  ERR_DU << "open_object(): fork() failed" << std::endl;
73  return false;
74  } else if(child == 0) {
75  execlp(launcher, launcher, path_or_url.c_str(), nullptr);
76  _exit(1); // This shouldn't happen.
77  }
78 
79  std::thread t { [child](){ int status; waitpid(child, &status, 0); } };
80  t.detach();
81 
82  return true;
83 
84 #elif defined(_WIN32)
85 
86  LOG_DU << "open_object(): on Win32, will use ShellExecute()\n";
87 
88  std::wstring u16path = unicode_cast<std::wstring>(path_or_url);
89 
90  const ptrdiff_t res = reinterpret_cast<ptrdiff_t>(ShellExecute(nullptr, L"open", u16path.c_str(), nullptr, nullptr, SW_SHOW));
91  if(res <= 32) {
92  ERR_DU << "open_object(): ShellExecute() failed (" << res << ")" << std::endl;
93  return false;
94  }
95 
96  return true;
97 
98 #else
99 
100  UNUSED(path_or_url); // silence gcc's -Wunused-parameter
101  ERR_DU << "open_object(): unsupported platform" << std::endl;
102  return false;
103 
104 #endif
105 }
106 
107 }
#define ERR_DU
Definition: open.cpp:41
ucs4_convert_impl::enableif< TD, typename TS::value_type >::type unicode_cast(const TS &source)
Desktop environment interaction functions.
#define LOG_DU
Definition: open.cpp:42
bool open_object(const std::string &path_or_url)
Opens the specified object with the default application configured for its type.
Definition: open.cpp:55
#define UNUSED(x)
Definition: global.hpp:34
bool open_object_is_supported()
Returns whether open_object() is supported/implemented for the current platform.
Definition: open.cpp:46
double t
Definition: astarsearch.cpp:64
Standard logging facilities (interface).
static lg::log_domain log_desktop("desktop")