diff options
author | wm4 <wm4@nowhere> | 2015-04-15 22:39:01 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-04-15 22:40:19 +0200 |
commit | dd12040ebe7c4006eab56c0d4a18d495274cf37d (patch) | |
tree | 83c0ce18519280a650ed34ef8df48f567cb4544e /video/out | |
parent | e6d7e550125873f46126f3d23c4970df1976a269 (diff) |
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.
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/x11_common.c | 67 | ||||
-rw-r--r-- | video/out/x11_common.h | 6 |
2 files changed, 61 insertions, 12 deletions
diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 392da3cee0..36a497055a 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -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; diff --git a/video/out/x11_common.h b/video/out/x11_common.h index f6d73dae00..eeff773bef 100644 --- a/video/out/x11_common.h +++ b/video/out/x11_common.h @@ -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; |