mirror of https://github.com/mpv-player/mpv
x11: actually disable screensaver
We already use 2 screensaver APIs when attempting to disable the screensaver: XResetScreenSaver() (from xlib) and XScreenSaverSuspend (from the X11 Screen Saver extension). None of these actually work. On modern desktop Linux, we are expected to make dbus calls using some freedesktop-defined protocol (and possibly we'd have to fallback to a Gnome specific one). At least xscreensaver doesn't respect the "old" APIs either. Solve this by running the xdg-screensaver script. It's a terrible, ugly piece of shit (just read the script if you disagree), but at least it appears to work everywhere. It's also simpler than involving various dbus client libraries. I hope this can replace the --heartbeat-cmd option, and maybe we could remove our own DPMS/XSS code too.
This commit is contained in:
parent
e6d7e55012
commit
dd12040ebe
|
@ -38,6 +38,10 @@
|
|||
#include "vo.h"
|
||||
#include "win_state.h"
|
||||
#include "osdep/timer.h"
|
||||
#include "osdep/subprocess.h"
|
||||
|
||||
// Specifically for mp_cancel
|
||||
#include "stream/stream.h"
|
||||
|
||||
#include <X11/Xmd.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
@ -470,6 +474,30 @@ static void vo_x11_get_bounding_monitors(struct vo_x11_state *x11, long b[4])
|
|||
#endif
|
||||
}
|
||||
|
||||
static void *screensaver_thread(void *arg)
|
||||
{
|
||||
struct vo_x11_state *x11 = arg;
|
||||
|
||||
for (;;) {
|
||||
sem_wait(&x11->screensaver_sem);
|
||||
// don't queue multiple wakeups
|
||||
while (!sem_trywait(&x11->screensaver_sem)) {}
|
||||
|
||||
if (mp_cancel_test(x11->screensaver_terminate))
|
||||
break;
|
||||
|
||||
char *args[] = {"xdg-screensaver", "reset", NULL};
|
||||
if (mp_subprocess(args, x11->screensaver_terminate, NULL, NULL,
|
||||
NULL, &(char*){0}))
|
||||
{
|
||||
MP_WARN(x11, "Disabling screensaver failed.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vo_x11_init(struct vo *vo)
|
||||
{
|
||||
struct mp_vo_opts *opts = vo->opts;
|
||||
|
@ -487,6 +515,14 @@ int vo_x11_init(struct vo *vo)
|
|||
};
|
||||
vo->x11 = x11;
|
||||
|
||||
x11->screensaver_terminate = mp_cancel_new(x11);
|
||||
sem_init(&x11->screensaver_sem, 0, 0);
|
||||
if (pthread_create(&x11->screensaver_thread, NULL, screensaver_thread, x11)) {
|
||||
x11->screensaver_terminate = NULL;
|
||||
sem_destroy(&x11->screensaver_sem);
|
||||
goto error;
|
||||
}
|
||||
|
||||
x11_error_output = x11->log;
|
||||
XSetErrorHandler(x11_errorhandler);
|
||||
|
||||
|
@ -498,13 +534,7 @@ int vo_x11_init(struct vo *vo)
|
|||
if (!x11->display) {
|
||||
MP_MSG(x11, vo->probing ? MSGL_V : MSGL_ERR,
|
||||
"couldn't open the X11 display (%s)!\n", dispName);
|
||||
|
||||
x11_error_output = NULL;
|
||||
XSetErrorHandler(NULL);
|
||||
|
||||
talloc_free(x11);
|
||||
vo->x11 = NULL;
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
x11->screen = DefaultScreen(x11->display); // screen ID
|
||||
x11->rootwin = RootWindow(x11->display, x11->screen); // root window ID
|
||||
|
@ -543,6 +573,10 @@ int vo_x11_init(struct vo *vo)
|
|||
vo_x11_update_geometry(vo);
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
vo_x11_uninit(vo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mp_keymap keymap[] = {
|
||||
|
@ -691,9 +725,18 @@ void vo_x11_uninit(struct vo *vo)
|
|||
MP_VERBOSE(x11, "uninit ...\n");
|
||||
if (x11->xim)
|
||||
XCloseIM(x11->xim);
|
||||
x11_error_output = NULL;
|
||||
XSetErrorHandler(NULL);
|
||||
XCloseDisplay(x11->display);
|
||||
if (x11->display) {
|
||||
x11_error_output = NULL;
|
||||
XSetErrorHandler(NULL);
|
||||
XCloseDisplay(x11->display);
|
||||
}
|
||||
|
||||
if (x11->screensaver_terminate) {
|
||||
mp_cancel_trigger(x11->screensaver_terminate);
|
||||
sem_post(&x11->screensaver_sem);
|
||||
pthread_join(x11->screensaver_thread, NULL);
|
||||
sem_destroy(&x11->screensaver_sem);
|
||||
}
|
||||
|
||||
talloc_free(x11);
|
||||
vo->x11 = NULL;
|
||||
|
@ -1766,7 +1809,7 @@ static void xscreensaver_heartbeat(struct vo_x11_state *x11)
|
|||
(time - x11->screensaver_time_last) >= 10)
|
||||
{
|
||||
x11->screensaver_time_last = time;
|
||||
|
||||
sem_post(&x11->screensaver_sem);
|
||||
XResetScreenSaver(x11->display);
|
||||
}
|
||||
}
|
||||
|
@ -1790,7 +1833,7 @@ static int xss_suspend(Display *mDisplay, Bool suspend)
|
|||
static void set_screensaver(struct vo_x11_state *x11, bool enabled)
|
||||
{
|
||||
Display *mDisplay = x11->display;
|
||||
if (x11->screensaver_enabled == enabled)
|
||||
if (!mDisplay || x11->screensaver_enabled == enabled)
|
||||
return;
|
||||
MP_VERBOSE(x11, "%s screensaver.\n", enabled ? "Enabling" : "Disabling");
|
||||
x11->screensaver_enabled = enabled;
|
||||
|
|
|
@ -20,9 +20,12 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include "osdep/semaphore.h"
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
struct vo;
|
||||
|
@ -57,6 +60,9 @@ struct vo_x11_state {
|
|||
bool screensaver_enabled;
|
||||
bool dpms_touched;
|
||||
double screensaver_time_last;
|
||||
pthread_t screensaver_thread;
|
||||
sem_t screensaver_sem;
|
||||
struct mp_cancel *screensaver_terminate;
|
||||
|
||||
XIM xim;
|
||||
XIC xic;
|
||||
|
|
Loading…
Reference in New Issue