From 4af00ae296b484fa088b4b9e40c8957cb32c0f96 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 20 Mar 2018 11:45:35 +0100 Subject: [PATCH] idle-monitor: Take idle inhibition into account Take idle inhibitions into account for when to fire idle watches as requested by OS components. This should stop gnome-session and gnome-settings-daemon considering the session idle when they have been inhibited for longer than their timeout, for example to avoid the screensaver activating, or the computer suspending after watching a film. https://bugzilla.gnome.org/show_bug.cgi?id=705942 --- src/Makefile.am | 1 + src/backends/gsm-inhibitor-flag.h | 36 ++++++++++ src/backends/meta-idle-monitor-private.h | 2 + src/backends/meta-idle-monitor.c | 92 +++++++++++++++++++++++- 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/backends/gsm-inhibitor-flag.h diff --git a/src/Makefile.am b/src/Makefile.am index 1579c8b9c..fd82d1f42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -161,6 +161,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ backends/meta-renderer-view.h \ backends/edid-parse.c \ backends/edid.h \ + backends/gsm-inhibitor-flag.h \ backends/x11/meta-backend-x11.c \ backends/x11/meta-backend-x11.h \ backends/x11/meta-barrier-x11.c \ diff --git a/src/backends/gsm-inhibitor-flag.h b/src/backends/gsm-inhibitor-flag.h new file mode 100644 index 000000000..40698f96a --- /dev/null +++ b/src/backends/gsm-inhibitor-flag.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __GSM_INHIBITOR_FLAG_H__ +#define __GSM_INHIBITOR_FLAG_H__ + +#include + +G_BEGIN_DECLS + +typedef enum { + GSM_INHIBITOR_FLAG_LOGOUT = 1 << 0, + GSM_INHIBITOR_FLAG_SWITCH_USER = 1 << 1, + GSM_INHIBITOR_FLAG_SUSPEND = 1 << 2, + GSM_INHIBITOR_FLAG_IDLE = 1 << 3, + GSM_INHIBITOR_FLAG_AUTOMOUNT = 1 << 4 +} GsmInhibitorFlag; + +G_END_DECLS + +#endif /* __GSM_INHIBITOR_FLAG_H__ */ diff --git a/src/backends/meta-idle-monitor-private.h b/src/backends/meta-idle-monitor-private.h index 89b80ba43..82f3f87b7 100644 --- a/src/backends/meta-idle-monitor-private.h +++ b/src/backends/meta-idle-monitor-private.h @@ -42,6 +42,8 @@ struct _MetaIdleMonitor { GObject parent_instance; + GDBusProxy *session_proxy; + gboolean inhibited; GHashTable *watches; int device_id; guint64 last_event_time; diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c index 3dc098f4d..46cf8cd76 100644 --- a/src/backends/meta-idle-monitor.c +++ b/src/backends/meta-idle-monitor.c @@ -36,6 +36,7 @@ #include #include #include +#include "gsm-inhibitor-flag.h" #include "meta-idle-monitor-private.h" #include "meta-idle-monitor-dbus.h" #include "meta-backend-private.h" @@ -87,6 +88,7 @@ meta_idle_monitor_dispose (GObject *object) MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); g_clear_pointer (&monitor->watches, g_hash_table_destroy); + g_clear_object (&monitor->session_proxy); G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object); } @@ -175,11 +177,93 @@ free_watch (gpointer data) g_slice_free (MetaIdleMonitorWatch, watch); } +static void +update_inhibited_watch (gpointer key, + gpointer value, + gpointer user_data) +{ + MetaIdleMonitor *monitor = user_data; + MetaIdleMonitorWatch *watch = value; + + if (!watch->timeout_source) + return; + + if (monitor->inhibited) + { + g_source_set_ready_time (watch->timeout_source, -1); + } + else + { + g_source_set_ready_time (watch->timeout_source, + monitor->last_event_time + + watch->timeout_msec * 1000); + } +} + +static void +update_inhibited (MetaIdleMonitor *monitor, + gboolean inhibited) +{ + if (inhibited == monitor->inhibited) + return; + + g_hash_table_foreach (monitor->watches, + update_inhibited_watch, + monitor); +} + +static void +meta_idle_monitor_inhibited_actions_changed (GDBusProxy *session, + GVariant *changed, + char **invalidated, + gpointer user_data) +{ + MetaIdleMonitor *monitor = user_data; + GVariant *v; + + v = g_variant_lookup_value (changed, "InhibitedActions", G_VARIANT_TYPE_UINT32); + if (v) + { + gboolean inhibited; + + inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE; + g_variant_unref (v); + + if (!inhibited) + monitor->last_event_time = g_get_monotonic_time (); + update_inhibited (monitor, inhibited); + } +} + static void meta_idle_monitor_init (MetaIdleMonitor *monitor) { + GVariant *v; + monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch); monitor->last_event_time = g_get_monotonic_time (); + + /* Monitor inhibitors */ + monitor->session_proxy = + g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + NULL, + NULL); + if (!monitor->session_proxy) + return; + + g_signal_connect (monitor->session_proxy, "g-properties-changed", + G_CALLBACK (meta_idle_monitor_inhibited_actions_changed), + monitor); + + v = g_dbus_proxy_get_cached_property (monitor->session_proxy, + "InhibitedActions"); + monitor->inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE; + g_variant_unref (v); } /** @@ -265,8 +349,12 @@ make_watch (MetaIdleMonitor *monitor, sizeof (GSource)); g_source_set_callback (source, NULL, watch, NULL); - g_source_set_ready_time (source, - monitor->last_event_time + timeout_msec * 1000); + if (!monitor->inhibited) + { + g_source_set_ready_time (source, + monitor->last_event_time + + timeout_msec * 1000); + } g_source_attach (source, NULL); g_source_unref (source);