mirror of
https://github.com/libretro/RetroArch
synced 2025-02-11 06:40:48 +00:00
WIP: Fixes #2026 Screensaver suspend on Linux via Dbus
One some systems (tested with Gnome 3 on Arch Linux) the current method of using `xdg-screensaver` to suspend the screensaver does not work. Instead, using DBus to issue an `Inhibit` request is recommended. The request returns a cookie that needs to be re-used to un-inhibit the screensaver later. Additionally if the DBus connection is closed the current inhibition is discarded. Thus, the DBus connection needs to stay connected for the duration of the screenshot inhibition. The code is heavily inspired from the [SDL 2.x code](http://hg.libsdl.org/SDL/file/default/src/core/linux/SDL_dbus.c#l172). I didn't call the SDL 2 code though since this it to fix the issue with the GL driver, and I assume one would want to have screensaver inhibited even when SDL 2 is not available (but GL is). I've set "WIP" because: * I haven't done C in a long time so my code is probably not great * There's a dependency on DBus which I don't know is acceptable or not * I've put my code where I could to check it works, but `x11_common` may not be the best place * The code need and "init" and "deinit" kind of method as it needs to initialise the DBus connection, and on deinit close it properly. I've used `x11_connect` and `x11_window_destroy` but they don't sound like the best choices. * I'm a bit unclear as to what happens when "suspend screensaver" is ticked on/off in the menu. This doesn't seem to call `x11_suspend_screensaver` everytime, so I'm not sure if there's a hook somewhere (as disabling screensaver suspend in the menu should cause a DBus unhinibit request to be sent). * Should I just call the SDL 2.x code (meaning that the GL driver would depend on SDL 2.x at runtime)? So, first of all are you ok with the approach, and if yes I'd gladly get feedback about the code, how to architecture it and the best place to put it. Thanks!
This commit is contained in:
parent
ea9793a17c
commit
05df632bd8
@ -612,6 +612,11 @@ ifeq ($(HAVE_XKBCOMMON), 1)
|
||||
LIBS += $(XKBCOMMON_LIBS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DBUS), 1)
|
||||
LIBS += $(DBUS_LIBS)
|
||||
CFLAGS += $(DBUS_CFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_UDEV), 1)
|
||||
DEFINES += $(UDEV_CFLAGS)
|
||||
LIBS += $(UDEV_LIBS)
|
||||
|
@ -34,6 +34,12 @@
|
||||
#include "../../verbosity.h"
|
||||
#include "../../runloop.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
static DBusConnection* dbus_connection;
|
||||
static unsigned int dbus_screensaver_cookie = 0;
|
||||
#endif
|
||||
|
||||
Colormap g_x11_cmap;
|
||||
Window g_x11_win;
|
||||
Display *g_x11_dpy;
|
||||
@ -146,6 +152,75 @@ void x11_set_window_attr(Display *dpy, Window win)
|
||||
}
|
||||
|
||||
void x11_suspend_screensaver(Window wnd, bool enable)
|
||||
{
|
||||
x11_suspend_screensaver_xdg_screensaver(wnd, enable);
|
||||
#ifdef HAVE_DBUS
|
||||
x11_suspend_screensaver_dbus(enable);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
void x11_suspend_screensaver_dbus(bool enable)
|
||||
{
|
||||
const char *app = "RetroArch";
|
||||
const char *reason = "Playing a game";
|
||||
DBusMessage *msg, *reply;
|
||||
|
||||
if (!enable)
|
||||
return;
|
||||
|
||||
if (dbus_screensaver_cookie > 0)
|
||||
return; // Already suspended
|
||||
|
||||
if (dbus_connection == NULL)
|
||||
return; // DBus connection was not obtained
|
||||
|
||||
|
||||
msg = dbus_message_new_method_call("org.freedesktop.ScreenSaver",
|
||||
"/org/freedesktop/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"Inhibit");
|
||||
|
||||
if (msg != NULL)
|
||||
{
|
||||
dbus_message_append_args(msg,
|
||||
DBUS_TYPE_STRING, &app,
|
||||
DBUS_TYPE_STRING, &reason,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
if (msg != NULL)
|
||||
{
|
||||
reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 300, NULL);
|
||||
if (reply != NULL) {
|
||||
if (!dbus_message_get_args(reply, NULL,
|
||||
DBUS_TYPE_UINT32, &dbus_screensaver_cookie,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
dbus_screensaver_cookie = 0;
|
||||
}
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
if (dbus_screensaver_cookie == 0)
|
||||
{
|
||||
RARCH_ERR("[DBus]: Failed to suspend screensaver via DBus.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_LOG("[DBus]: Suspended screensaver.\n");
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void x11_suspend_screensaver_xdg_screensaver(Window wnd, bool enable)
|
||||
{
|
||||
int ret;
|
||||
char cmd[64] = {0};
|
||||
@ -533,6 +608,22 @@ bool x11_connect(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
DBusError err;
|
||||
int ret;
|
||||
dbus_error_init(&err);
|
||||
|
||||
dbus_connection = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
RARCH_ERR("[DBus]: Failed to get DBus connection. Screensaver will not be suspended.\n");
|
||||
dbus_error_free(&err);
|
||||
}
|
||||
if (dbus_connection != NULL) {
|
||||
dbus_connection_set_exit_on_disconnect(dbus_connection, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -573,6 +664,32 @@ void x11_window_destroy(bool fullscreen)
|
||||
if (!fullscreen)
|
||||
XDestroyWindow(g_x11_dpy, g_x11_win);
|
||||
g_x11_win = None;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
if (dbus_connection != NULL)
|
||||
{
|
||||
|
||||
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, &dbus_screensaver_cookie,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (msg != NULL) {
|
||||
if (dbus_connection_send(dbus_connection, msg, NULL)) {
|
||||
dbus_connection_flush(dbus_connection);
|
||||
}
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
dbus_screensaver_cookie = 0;
|
||||
|
||||
dbus_connection_close(dbus_connection);
|
||||
dbus_connection_unref(dbus_connection);
|
||||
dbus_shutdown();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void x11_colormap_destroy(void)
|
||||
|
@ -44,6 +44,10 @@ void x11_save_last_used_monitor(Window win);
|
||||
void x11_show_mouse(Display *dpy, Window win, bool state);
|
||||
void x11_windowed_fullscreen(Display *dpy, Window win);
|
||||
void x11_suspend_screensaver(Window win, bool enable);
|
||||
void x11_suspend_screensaver_xdg_screensaver(Window win, bool enable);
|
||||
#ifdef HAVE_DBUS
|
||||
void x11_suspend_screensaver_dbus(bool enable);
|
||||
#endif
|
||||
bool x11_enter_fullscreen(Display *dpy, unsigned width,
|
||||
unsigned height, XF86VidModeModeInfo *desktop_mode);
|
||||
|
||||
|
@ -382,6 +382,7 @@ check_pkgconf XCB xcb
|
||||
check_pkgconf WAYLAND wayland-egl
|
||||
|
||||
check_pkgconf XKBCOMMON xkbcommon 0.3.2
|
||||
check_pkgconf DBUS dbus-1
|
||||
check_pkgconf XEXT xext
|
||||
check_pkgconf XF86VM xxf86vm
|
||||
check_pkgconf XINERAMA xinerama
|
||||
|
Loading…
x
Reference in New Issue
Block a user