summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2018-03-20 11:45:35 +0100
committerJonas Ã…dahl <jadahl@gmail.com>2018-04-16 13:28:03 +0200
commit4af00ae296b484fa088b4b9e40c8957cb32c0f96 (patch)
treeacdebaf9f5605039c39288c7f9f73f49327a35f8
parent84e575be775c49f1e13c5c99842f89ed2378b091 (diff)
downloadmutter-4af00ae296b484fa088b4b9e40c8957cb32c0f96.tar.gz
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
-rw-r--r--src/Makefile.am1
-rw-r--r--src/backends/gsm-inhibitor-flag.h36
-rw-r--r--src/backends/meta-idle-monitor-private.h2
-rw-r--r--src/backends/meta-idle-monitor.c92
4 files changed, 129 insertions, 2 deletions
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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSM_INHIBITOR_FLAG_H__
+#define __GSM_INHIBITOR_FLAG_H__
+
+#include <glib-object.h>
+
+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 <meta/util.h>
#include <meta/main.h>
#include <meta/meta-idle-monitor.h>
+#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);
}
@@ -176,10 +178,92 @@ free_watch (gpointer data)
}
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);