summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2012-11-06 17:47:24 -0500
committerColin Walters <walters@verbum.org>2012-11-06 21:04:11 -0500
commit92c64b500a91f2f5289b972961f85f8d268ab88f (patch)
tree1f51cde658f494bcb229d21262ff862bc7f703d8
parent5aff5ed2e24146f16c6eabbd4f39e9c9fc28dbb9 (diff)
downloadgnome-session-wip/isactive.tar.gz
[wip] Add new SessionIsActive propertywip/isactive
Merge the code from gnome-settings-daemon to monitor session active state, unfortunately down-porting it to dbus-glib in the ConsoleKit case. Even more unfortunately, we hand-roll a PropertiesChanged signal for GDBus consuemrs.
-rw-r--r--gnome-session/gsm-consolekit.c90
-rw-r--r--gnome-session/gsm-manager.c67
-rw-r--r--gnome-session/gsm-system.c26
-rw-r--r--gnome-session/gsm-system.h2
-rw-r--r--gnome-session/gsm-systemd.c201
-rw-r--r--gnome-session/org.gnome.SessionManager.xml9
6 files changed, 369 insertions, 26 deletions
diff --git a/gnome-session/gsm-consolekit.c b/gnome-session/gsm-consolekit.c
index 4c0eca56..c20004af 100644
--- a/gnome-session/gsm-consolekit.c
+++ b/gnome-session/gsm-consolekit.c
@@ -56,6 +56,13 @@ struct _GsmConsolekitPrivate
DBusGProxy *bus_proxy;
DBusGProxy *ck_proxy;
UpClient *up_client;
+
+ gboolean is_active;
+};
+
+enum {
+ PROP_0,
+ PROP_ACTIVE
};
static void gsm_consolekit_class_init (GsmConsolekitClass *klass);
@@ -81,14 +88,53 @@ G_DEFINE_TYPE_WITH_CODE (GsmConsolekit, gsm_consolekit, G_TYPE_OBJECT,
gsm_consolekit_system_init))
static void
+gsm_consolekit_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsmConsolekit *self = GSM_CONSOLEKIT (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE:
+ self->priv->is_active = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gsm_consolekit_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsmConsolekit *self = GSM_CONSOLEKIT (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, self->priv->is_active);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
gsm_consolekit_class_init (GsmConsolekitClass *manager_class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (manager_class);
+ object_class->get_property = gsm_consolekit_get_property;
+ object_class->set_property = gsm_consolekit_set_property;
object_class->finalize = gsm_consolekit_finalize;
+ g_object_class_override_property (object_class, PROP_ACTIVE, "active");
+
g_type_class_add_private (manager_class, sizeof (GsmConsolekitPrivate));
}
@@ -112,6 +158,41 @@ gsm_consolekit_dbus_filter (DBusConnection *connection,
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
+static void
+is_active_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ gpointer data)
+{
+ GsmConsolekit *self = data;
+ GError *local_error = NULL;
+ gboolean is_active;
+
+ if (!dbus_g_proxy_end_call (proxy, call, &local_error,
+ G_TYPE_BOOLEAN, &is_active,
+ G_TYPE_INVALID)) {
+ g_warning ("Failed isActive call to ConsoleKit: %s",
+ local_error->message);
+ g_clear_error (&local_error);
+ return;
+ }
+
+ if (is_active != self->priv->is_active) {
+ self->priv->is_active = is_active;
+ g_object_notify ((GObject*) self, "active");
+ }
+}
+
+static void
+on_active_changed (DBusGProxy *proxy,
+ gboolean is_active,
+ GsmConsolekit *self)
+{
+ if (is_active != self->priv->is_active) {
+ self->priv->is_active = is_active;
+ g_object_notify ((GObject*) self, "active");
+ }
+}
+
static gboolean
gsm_consolekit_ensure_ck_connection (GsmConsolekit *manager,
GError **error)
@@ -180,6 +261,15 @@ gsm_consolekit_ensure_ck_connection (GsmConsolekit *manager,
is_connected = FALSE;
goto out;
}
+
+ dbus_g_proxy_begin_call (manager->priv->ck_proxy,
+ "IsActive",
+ is_active_cb, g_object_ref (manager),
+ (GDestroyNotify)g_object_unref,
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (manager->priv->ck_proxy, "ActiveChanged", G_TYPE_BOOLEAN, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (manager->priv->ck_proxy, "ActiveChanged",
+ G_CALLBACK (on_active_changed), manager, NULL);
}
is_connected = TRUE;
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
index 192c81df..52f4b0f9 100644
--- a/gnome-session/gsm-manager.c
+++ b/gnome-session/gsm-manager.c
@@ -165,6 +165,7 @@ enum {
PROP_0,
PROP_CLIENT_STORE,
PROP_SESSION_NAME,
+ PROP_SESSION_IS_ACTIVE,
PROP_FALLBACK,
PROP_FAILSAFE
};
@@ -2434,6 +2435,9 @@ gsm_manager_get_property (GObject *object,
case PROP_SESSION_NAME:
g_value_set_string (value, self->priv->session_name);
break;
+ case PROP_SESSION_IS_ACTIVE:
+ g_value_set_boolean (value, gsm_system_is_active (self->priv->system));
+ break;
case PROP_FALLBACK:
g_value_set_boolean (value, self->priv->is_fallback_session);
break;
@@ -2633,6 +2637,20 @@ gsm_manager_class_init (GsmManagerClass *klass)
NULL,
NULL,
G_PARAM_READABLE));
+ /**
+
+ * GsmManager::session-is-active
+ *
+ * If true, the current session is in the foreground and
+ * available for user input.
+ */
+ g_object_class_install_property (object_class,
+ PROP_SESSION_IS_ACTIVE,
+ g_param_spec_boolean ("session-is-active",
+ NULL,
+ NULL,
+ TRUE,
+ G_PARAM_READABLE));
/**
* GsmManager::fallback
@@ -2675,6 +2693,53 @@ on_presence_status_changed (GsmPresence *presence,
g_object_unref (system);
}
+static void
+on_gsm_system_active_changed (GsmSystem *system,
+ GParamSpec *pspec,
+ GsmManager *self)
+{
+ DBusGConnection *gconnection;
+ DBusConnection *connection;
+ DBusMessage *message;
+ DBusMessageIter iter;
+ DBusMessageIter subiter;
+ DBusMessageIter dict_iter;
+ DBusMessageIter v_iter;
+ dbus_bool_t is_active;
+ const char *prop_name = "SessionIsActive";
+
+ g_object_notify ((GObject*)self, "session-is-active");
+
+ /* Now, the following bits emit the PropertiesChanged signal
+ * that GDBus expects. This code should just die in a port to
+ * GDBus.
+ */
+ gconnection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+ g_assert (gconnection);
+ connection = dbus_g_connection_get_connection (gconnection);
+ is_active = gsm_system_is_active (self->priv->system);
+ message = dbus_message_new_signal (GSM_MANAGER_DBUS_PATH, "org.freedesktop.DBus.Properties",
+ "PropertiesChanged");
+ g_assert (message != NULL);
+ dbus_message_iter_init_append (message, &iter);
+ /* changed */
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &subiter);
+ dbus_message_iter_open_container (&subiter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter);
+ dbus_message_iter_append_basic (&dict_iter, DBUS_TYPE_STRING, &prop_name);
+ dbus_message_iter_open_container (&dict_iter, DBUS_TYPE_VARIANT, "b", &v_iter);
+ dbus_message_iter_append_basic (&v_iter, DBUS_TYPE_BOOLEAN, &is_active);
+ dbus_message_iter_close_container (&dict_iter, &v_iter);
+ dbus_message_iter_close_container (&subiter, &dict_iter);
+ dbus_message_iter_close_container (&iter, &subiter);
+ /* invalidated */
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &subiter);
+ dbus_message_iter_close_container (&iter, &subiter);
+
+ g_printerr ("SESSION: EMIT ACTIVE CHANGED %d\n", is_active);
+ dbus_connection_send (connection, message, NULL);
+ dbus_message_unref (message);
+}
+
static gboolean
idle_timeout_get_mapping (GValue *value,
GVariant *variant,
@@ -2727,6 +2792,8 @@ gsm_manager_init (GsmManager *manager)
NULL, NULL);
manager->priv->system = gsm_get_system ();
+ g_signal_connect (manager->priv->system, "notify::active",
+ G_CALLBACK (on_gsm_system_active_changed), manager);
manager->priv->shell = gsm_get_shell ();
}
diff --git a/gnome-session/gsm-system.c b/gnome-session/gsm-system.c
index 7ace678d..49a4316d 100644
--- a/gnome-session/gsm-system.c
+++ b/gnome-session/gsm-system.c
@@ -32,6 +32,11 @@ enum {
LAST_SIGNAL
};
+enum {
+ PROP_0,
+ PROP_ACTIVE
+};
+
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_INTERFACE (GsmSystem, gsm_system, G_TYPE_OBJECT)
@@ -39,6 +44,7 @@ G_DEFINE_INTERFACE (GsmSystem, gsm_system, G_TYPE_OBJECT)
static void
gsm_system_default_init (GsmSystemInterface *iface)
{
+ GParamSpec *pspec;
signals [REQUEST_COMPLETED] =
g_signal_new ("request-completed",
GSM_TYPE_SYSTEM,
@@ -47,6 +53,12 @@ gsm_system_default_init (GsmSystemInterface *iface)
NULL, NULL, NULL,
G_TYPE_NONE,
1, G_TYPE_POINTER);
+ pspec = g_param_spec_boolean ("active",
+ "Active",
+ "Whether or not session is active",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+ g_object_interface_install_property (iface, pspec);
}
GQuark
@@ -143,6 +155,20 @@ gsm_system_is_login_session (GsmSystem *system)
return GSM_SYSTEM_GET_IFACE (system)->is_login_session (system);
}
+/**
+ * gsm_system_is_active:
+ *
+ * Returns: %TRUE if the current session is in the foreground
+ * Since: 3.8
+ */
+gboolean
+gsm_system_is_active (GsmSystem *system)
+{
+ gboolean is_active;
+ g_object_get ((GObject*)system, "active", &is_active, NULL);
+ return is_active;
+}
+
GsmSystem *
gsm_get_system (void)
{
diff --git a/gnome-session/gsm-system.h b/gnome-session/gsm-system.h
index b284e16b..69418238 100644
--- a/gnome-session/gsm-system.h
+++ b/gnome-session/gsm-system.h
@@ -102,6 +102,8 @@ void gsm_system_set_session_idle (GsmSystem *system,
gboolean gsm_system_is_login_session (GsmSystem *system);
+gboolean gsm_system_is_active (GsmSystem *system);
+
void gsm_system_add_inhibitor (GsmSystem *system,
const gchar *id,
GsmInhibitorFlag flags);
diff --git a/gnome-session/gsm-systemd.c b/gnome-session/gsm-systemd.c
index 417bb601..92df6b2f 100644
--- a/gnome-session/gsm-systemd.c
+++ b/gnome-session/gsm-systemd.c
@@ -51,12 +51,20 @@
struct _GsmSystemdPrivate
{
+ GSource *sd_source;
GDBusProxy *sd_proxy;
- gchar *session_id;
+ char *session_id;
gchar *session_path;
GSList *inhibitors;
gint inhibit_fd;
+
+ gboolean is_active;
+};
+
+enum {
+ PROP_0,
+ PROP_ACTIVE
};
static void gsm_systemd_system_init (GsmSystemInterface *iface);
@@ -81,9 +89,13 @@ gsm_systemd_finalize (GObject *object)
GsmSystemd *systemd = GSM_SYSTEMD (object);
g_clear_object (&systemd->priv->sd_proxy);
- g_free (systemd->priv->session_id);
+ free (systemd->priv->session_id);
g_free (systemd->priv->session_path);
+ if (systemd->priv->sd_source) {
+ g_source_destroy (systemd->priv->sd_source);
+ }
+
if (systemd->priv->inhibitors != NULL) {
g_slist_free_full (systemd->priv->inhibitors, g_free);
}
@@ -93,21 +105,157 @@ gsm_systemd_finalize (GObject *object)
}
static void
+gsm_systemd_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsmSystemd *self = GSM_SYSTEMD (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE:
+ self->priv->is_active = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gsm_systemd_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsmSystemd *self = GSM_SYSTEMD (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, self->priv->is_active);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
gsm_systemd_class_init (GsmSystemdClass *manager_class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (manager_class);
+ object_class->get_property = gsm_systemd_get_property;
+ object_class->set_property = gsm_systemd_set_property;
object_class->finalize = gsm_systemd_finalize;
+ g_object_class_override_property (object_class, PROP_ACTIVE, "active");
+
g_type_class_add_private (manager_class, sizeof (GsmSystemdPrivate));
}
+typedef struct
+{
+ GSource source;
+ GPollFD pollfd;
+ sd_login_monitor *monitor;
+} SdSource;
+
+static gboolean
+sd_source_prepare (GSource *source,
+ gint *timeout)
+{
+ *timeout = -1;
+ return FALSE;
+}
+
+static gboolean
+sd_source_check (GSource *source)
+{
+ SdSource *sd_source = (SdSource *)source;
+
+ return sd_source->pollfd.revents != 0;
+}
+
+static gboolean
+sd_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+
+{
+ SdSource *sd_source = (SdSource *)source;
+ gboolean ret;
+
+ g_warn_if_fail (callback != NULL);
+
+ ret = (*callback) (user_data);
+
+ sd_login_monitor_flush (sd_source->monitor);
+ return ret;
+}
+
+static void
+sd_source_finalize (GSource *source)
+{
+ SdSource *sd_source = (SdSource*)source;
+
+ sd_login_monitor_unref (sd_source->monitor);
+}
+
+static GSourceFuncs sd_source_funcs = {
+ sd_source_prepare,
+ sd_source_check,
+ sd_source_dispatch,
+ sd_source_finalize
+};
+
+static GSource *
+sd_source_new (void)
+{
+ GSource *source;
+ SdSource *sd_source;
+ int ret;
+
+ source = g_source_new (&sd_source_funcs, sizeof (SdSource));
+ sd_source = (SdSource *)source;
+
+ if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0) {
+ g_warning ("Error getting login monitor: %d", ret);
+ } else {
+ sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor);
+ sd_source->pollfd.events = G_IO_IN;
+ g_source_add_poll (source, &sd_source->pollfd);
+ }
+
+ return source;
+}
+
+static gboolean
+on_sd_source_changed (gpointer user_data)
+{
+ GsmSystemd *self = user_data;
+ int active_r;
+ gboolean active;
+
+ active_r = sd_session_is_active (self->priv->session_id);
+ if (active_r < 0)
+ active = FALSE;
+ else
+ active = active_r;
+ if (active != self->priv->is_active) {
+ g_printerr ("SESSION: NOTIFY ACTIVE %d -> %d\n", self->priv->is_active, active);
+ self->priv->is_active = active;
+ g_object_notify (G_OBJECT (self), "active");
+ }
+
+ return TRUE;
+}
+
static void
gsm_systemd_init (GsmSystemd *manager)
{
- GError *error;
+ GError *error = NULL;
GDBusConnection *bus;
GVariant *res;
@@ -117,33 +265,26 @@ gsm_systemd_init (GsmSystemd *manager)
manager->priv->inhibit_fd = -1;
- error = NULL;
-
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
- if (bus == NULL) {
- g_warning ("Failed to connect to system bus: %s",
+ if (bus == NULL)
+ g_error ("Failed to connect to system bus: %s",
+ error->message);
+ manager->priv->sd_proxy =
+ g_dbus_proxy_new_sync (bus,
+ 0,
+ NULL,
+ SD_NAME,
+ SD_PATH,
+ SD_INTERFACE,
+ NULL,
+ &error);
+ if (manager->priv->sd_proxy == NULL) {
+ g_warning ("Failed to connect to systemd: %s",
error->message);
- g_error_free (error);
- } else {
- manager->priv->sd_proxy =
- g_dbus_proxy_new_sync (bus,
- 0,
- NULL,
- SD_NAME,
- SD_PATH,
- SD_INTERFACE,
- NULL,
- &error);
-
- if (manager->priv->sd_proxy == NULL) {
- g_warning ("Failed to connect to systemd: %s",
- error->message);
- g_error_free (error);
- }
-
- g_object_unref (bus);
+ g_clear_error (&error);
}
+
sd_pid_get_session (getpid (), &manager->priv->session_id);
if (manager->priv->session_id == NULL) {
@@ -161,6 +302,14 @@ gsm_systemd_init (GsmSystemd *manager)
NULL);
g_variant_get (res, "(o)", &manager->priv->session_path);
g_variant_unref (res);
+
+ manager->priv->sd_source = sd_source_new ();
+ g_source_set_callback (manager->priv->sd_source, on_sd_source_changed, manager, NULL);
+ g_source_attach (manager->priv->sd_source, NULL);
+
+ on_sd_source_changed (manager);
+
+ g_object_unref (bus);
}
static void
diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml
index 8ed6bda5..b1d459d7 100644
--- a/gnome-session/org.gnome.SessionManager.xml
+++ b/gnome-session/org.gnome.SessionManager.xml
@@ -408,5 +408,14 @@
</doc:doc>
</property>
+ <property name="SessionIsActive" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>If true, the session is currently in the
+ foreground and available for user input.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
</interface>
</node>