From 6694048272619b7f91d161c040b818ff63e65279 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 15 Aug 2017 20:32:44 +0200 Subject: x11: use xdg-screensaver suspend/resume If it doesn't work this time, I'll remove all X11 screensaver code. Fixes #4763. --- video/out/x11_common.c | 94 ++++++++++++++++++++++++++++++++------------------ video/out/x11_common.h | 11 +++--- 2 files changed, 65 insertions(+), 40 deletions(-) diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 41c9d8b00a..a8e8d1f829 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -37,6 +37,8 @@ #include #include +#include "osdep/atomic.h" + #include "config.h" #include "misc/bstr.h" #include "options/options.h" @@ -135,7 +137,6 @@ static atomic_int x11_error_silence; static void vo_x11_update_geometry(struct vo *vo); static void vo_x11_fullscreen(struct vo *vo); -static void xscreensaver_heartbeat(struct vo_x11_state *x11); static void set_screensaver(struct vo_x11_state *x11, bool enabled); static void vo_x11_selectinput_witherr(struct vo *vo, Display *display, Window w, long event_mask); @@ -503,27 +504,63 @@ static void vo_x11_get_bounding_monitors(struct vo_x11_state *x11, long b[4]) static void *screensaver_thread(void *arg) { struct vo_x11_state *x11 = arg; + bool suspend = false; + bool run = true; + + while (run) { + pthread_mutex_lock(&x11->screensaver_thread_lock); + bool suspend_new = suspend; + for (;;) { + run = x11->screensaver_thread_running; + suspend_new = x11->screensaver_thread_suspend; + if (!run || suspend != suspend_new) + break; + pthread_cond_wait(&x11->screensaver_thread_wakeup, + &x11->screensaver_thread_lock); + } + pthread_mutex_unlock(&x11->screensaver_thread_lock); - for (;;) { - sem_wait(&x11->screensaver_sem); - // don't queue multiple wakeups - while (!sem_trywait(&x11->screensaver_sem)) {} - - if (atomic_load(&x11->screensaver_terminate)) - break; + if (!run) { + suspend_new = false; // make sure to resume on exit + if (suspend == suspend_new) + break; + } - char *args[] = {"xdg-screensaver", "reset", NULL}; - int status = mp_subprocess(args, NULL, NULL, mp_devnull, mp_devnull, &(char*){0}); + char *args[] = {"xdg-screensaver", suspend_new ? "suspend" : "resume", + mp_tprintf(32, "%lx", x11->screensaver_thread_window), + NULL}; + int status = mp_subprocess(args, NULL, NULL, mp_devnull, mp_devnull, + &(char*){0}); if (status) { - MP_VERBOSE(x11, "Disabling screensaver failed (%d). Make sure the " + MP_VERBOSE(x11, "Updating screensaver failed (%d). Make sure the " "xdg-screensaver script is installed.\n", status); break; } + + suspend = suspend_new; } return NULL; } +static void screensaver_thread_update(struct vo_x11_state *x11) +{ + if (!x11->screensaver_thread_running && x11->window) { + x11->screensaver_thread_window = x11->window; + x11->screensaver_thread_running = true; + if (pthread_create(&x11->screensaver_thread, NULL, screensaver_thread, x11)) + x11->screensaver_thread_running = false; + } + + if (!x11->screensaver_thread_running) + return; + + pthread_mutex_lock(&x11->screensaver_thread_lock); + x11->screensaver_thread_suspend = !x11->screensaver_enabled; + pthread_cond_signal(&x11->screensaver_thread_wakeup); + pthread_mutex_unlock(&x11->screensaver_thread_lock); +} + int vo_x11_init(struct vo *vo) { struct mp_vo_opts *opts = vo->opts; @@ -544,12 +581,8 @@ int vo_x11_init(struct vo *vo) }; vo->x11 = x11; - sem_init(&x11->screensaver_sem, 0, 0); - if (pthread_create(&x11->screensaver_thread, NULL, screensaver_thread, x11)) { - sem_destroy(&x11->screensaver_sem); - goto error; - } - x11->screensaver_thread_running = true; + pthread_mutex_init(&x11->screensaver_thread_lock, NULL); + pthread_cond_init(&x11->screensaver_thread_wakeup, NULL); x11_error_output = x11->log; XSetErrorHandler(x11_errorhandler); @@ -773,12 +806,16 @@ void vo_x11_uninit(struct vo *vo) } if (x11->screensaver_thread_running) { - atomic_store(&x11->screensaver_terminate, true); - sem_post(&x11->screensaver_sem); + pthread_mutex_lock(&x11->screensaver_thread_lock); + x11->screensaver_thread_running = false; + pthread_cond_signal(&x11->screensaver_thread_wakeup); + pthread_mutex_unlock(&x11->screensaver_thread_lock); pthread_join(x11->screensaver_thread, NULL); - sem_destroy(&x11->screensaver_sem); } + pthread_mutex_destroy(&x11->screensaver_thread_lock); + pthread_cond_destroy(&x11->screensaver_thread_wakeup); + if (x11->wakeup_pipe[0] >= 0) { close(x11->wakeup_pipe[0]); close(x11->wakeup_pipe[1]); @@ -1041,8 +1078,6 @@ void vo_x11_check_events(struct vo *vo) Display *display = vo->x11->display; XEvent Event; - xscreensaver_heartbeat(vo->x11); - while (XPending(display)) { XNextEvent(display, &Event); MP_TRACE(x11, "XEvent: %d\n", Event.type); @@ -1424,6 +1459,8 @@ static void vo_x11_create_window(struct vo *vo, XVisualInfo *vis, vo_x11_set_property_utf8(vo, XA(x11, _GTK_THEME_VARIANT), "dark"); } vo_x11_xembed_update(x11, 0); + + screensaver_thread_update(x11); } static void vo_x11_map_window(struct vo *vo, struct mp_rect rc) @@ -1898,18 +1935,6 @@ void vo_x11_wait_events(struct vo *vo, int64_t until_time_us) mp_flush_wakeup_pipe(x11->wakeup_pipe[0]); } -static void xscreensaver_heartbeat(struct vo_x11_state *x11) -{ - double time = mp_time_sec(); - - if (x11->display && !x11->screensaver_enabled && - (time - x11->screensaver_time_last) >= 10) - { - x11->screensaver_time_last = time; - sem_post(&x11->screensaver_sem); - } -} - static void set_screensaver(struct vo_x11_state *x11, bool enabled) { Display *mDisplay = x11->display; @@ -1917,6 +1942,7 @@ static void set_screensaver(struct vo_x11_state *x11, bool enabled) return; MP_VERBOSE(x11, "%s screensaver.\n", enabled ? "Enabling" : "Disabling"); x11->screensaver_enabled = enabled; + screensaver_thread_update(x11); int nothing; if (DPMSQueryExtension(mDisplay, ¬hing, ¬hing)) { BOOL onoff = 0; diff --git a/video/out/x11_common.h b/video/out/x11_common.h index e69640cc64..b2f6336d25 100644 --- a/video/out/x11_common.h +++ b/video/out/x11_common.h @@ -24,9 +24,6 @@ #include #include -#include "osdep/atomic.h" -#include "osdep/semaphore.h" - #include "common/common.h" struct vo; @@ -66,11 +63,13 @@ struct vo_x11_state { bool screensaver_enabled; bool dpms_touched; - double screensaver_time_last; + + long screensaver_thread_window; pthread_t screensaver_thread; + pthread_mutex_t screensaver_thread_lock; + pthread_cond_t screensaver_thread_wakeup; bool screensaver_thread_running; - sem_t screensaver_sem; - atomic_bool screensaver_terminate; + bool screensaver_thread_suspend; XIM xim; XIC xic; -- cgit v1.2.3