boo/lib/x11/ApplicationUnix.cpp

148 lines
4.9 KiB
C++
Raw Normal View History

2015-05-06 00:50:57 +00:00
/* Meta-implementation for dynamically-constructing user's preferred
* platform interface
*/
2015-08-18 19:40:26 +00:00
#define APPLICATION_UNIX_CPP
#include <cstdint>
#include <cstdlib>
#include "boo/IApplication.hpp"
#include <dbus/dbus.h>
#include <logvisor/logvisor.hpp>
#include <unistd.h>
namespace boo {
static logvisor::Module Log("boo::ApplicationUnix");
IApplication* APP = nullptr;
class ScreenSaverInhibitor {
DBusConnection* m_dbus;
uint64_t m_wid;
DBusPendingCall* m_pending = nullptr;
uint32_t m_cookie = UINT32_MAX;
static void Callback(DBusPendingCall* pending, ScreenSaverInhibitor* user_data) {
user_data->HandleReply();
}
void HandleReply() {
DBusMessage* msg = nullptr;
DBusError err = DBUS_ERROR_INIT;
if ((msg = dbus_pending_call_steal_reply(m_pending)) &&
dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &m_cookie, DBUS_TYPE_INVALID)) {
2019-07-20 04:22:36 +00:00
Log.report(logvisor::Info, fmt("Screen saver inhibited"));
} else {
/* Fallback to xdg-screensaver */
dbus_error_free(&err);
2019-07-20 04:22:36 +00:00
Log.report(logvisor::Info, fmt("Falling back to xdg-screensaver inhibit"));
if (!fork()) {
2019-07-20 04:22:36 +00:00
execlp("xdg-screensaver", "xdg-screensaver", "suspend", fmt::format(fmt("0x{:X}"), m_wid).c_str(), nullptr);
exit(1);
}
}
if (msg)
dbus_message_unref(msg);
dbus_pending_call_unref(m_pending);
m_pending = nullptr;
}
public:
ScreenSaverInhibitor(DBusConnection* dbus, uint64_t wid) : m_dbus(dbus), m_wid(wid) {
#ifndef BOO_MSAN
DBusMessage* msg =
dbus_message_new_method_call("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver", "Inhibit");
const char* appName = APP->getUniqueName().data();
const char* reason = "Game Active";
dbus_message_append_args(msg, DBUS_TYPE_STRING, &appName, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID);
dbus_connection_send_with_reply(m_dbus, msg, &m_pending, -1);
dbus_pending_call_set_notify(m_pending, DBusPendingCallNotifyFunction(Callback), this, nullptr);
dbus_message_unref(msg);
dbus_connection_flush(m_dbus);
#endif
}
~ScreenSaverInhibitor() {
#ifndef BOO_MSAN
if (m_cookie != UINT32_MAX) {
DBusMessage* msg =
dbus_message_new_method_call("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver", "UnInhibit");
dbus_message_append_args(msg, DBUS_TYPE_UINT32, &m_cookie, DBUS_TYPE_INVALID);
dbus_connection_send(m_dbus, msg, nullptr);
dbus_message_unref(msg);
dbus_connection_flush(m_dbus);
}
#endif
}
};
}
#include "ApplicationXlib.hpp"
2015-08-18 19:40:26 +00:00
#include "ApplicationWayland.hpp"
2015-05-06 00:50:57 +00:00
2015-08-18 22:43:30 +00:00
#include <memory>
2017-12-29 07:54:26 +00:00
#include <cstdio>
2015-05-13 22:21:13 +00:00
2018-01-02 05:09:15 +00:00
/* No icon by default */
2018-12-08 05:17:51 +00:00
extern "C" const uint8_t MAINICON_NETWM[] __attribute__((weak)) = {};
extern "C" const size_t MAINICON_NETWM_SZ __attribute__((weak)) = 0;
2018-01-02 05:09:15 +00:00
2018-12-08 05:17:51 +00:00
DBusConnection* RegisterDBus(const char* appName, bool& isFirst) {
isFirst = true;
DBusError err = {};
dbus_error_init(&err);
2015-05-13 22:21:13 +00:00
2018-12-08 05:17:51 +00:00
/* connect to the bus and check for errors */
DBusConnection* conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err)) {
2019-07-20 04:22:36 +00:00
fmt::print(stderr, fmt("DBus Connection Error ({})\n"), err.message);
2018-12-08 05:17:51 +00:00
dbus_error_free(&err);
}
if (conn == nullptr)
return nullptr;
2015-05-13 22:21:13 +00:00
2018-12-08 05:17:51 +00:00
/* request our name on the bus and check for errors */
2019-07-20 04:22:36 +00:00
int ret = dbus_bus_request_name(conn, fmt::format(fmt("boo.{}.unique"), appName).c_str(),
DBUS_NAME_FLAG_DO_NOT_QUEUE, &err);
2018-12-08 05:17:51 +00:00
if (dbus_error_is_set(&err)) {
2019-07-20 04:22:36 +00:00
fmt::print(stderr, fmt("DBus Name Error ({})\n"), err.message);
2018-12-08 05:17:51 +00:00
dbus_error_free(&err);
dbus_connection_close(conn);
return nullptr;
2018-12-08 05:17:51 +00:00
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret)
isFirst = false;
2015-05-13 22:21:13 +00:00
2018-12-08 05:17:51 +00:00
return conn;
2015-05-13 22:21:13 +00:00
}
2018-12-08 05:17:51 +00:00
namespace boo {
2015-05-06 00:50:57 +00:00
2018-12-08 05:17:51 +00:00
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, std::string_view uniqueName,
std::string_view friendlyName, std::string_view pname, const std::vector<std::string>& args,
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
bool singleInstance) {
std::string thrName = std::string(friendlyName) + " Main";
logvisor::RegisterThreadName(thrName.c_str());
if (APP)
return 1;
if (platform == IApplication::EPlatformType::Wayland)
APP = new ApplicationWayland(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
singleInstance);
else if (platform == IApplication::EPlatformType::Xlib || platform == IApplication::EPlatformType::Auto)
APP = new ApplicationXlib(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
singleInstance);
else
return 1;
int ret = APP->run();
delete APP;
APP = nullptr;
return ret;
2015-05-06 00:50:57 +00:00
}
2018-12-08 05:17:51 +00:00
} // namespace boo