[gnome-flashback] screensaver: add GfListener
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] screensaver: add GfListener
- Date: Sun, 31 Jul 2016 22:13:47 +0000 (UTC)
commit 8ae2abc21558c29f10825c5bbc051be6c7426fbb
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sun Jul 31 23:36:00 2016 +0300
screensaver: add GfListener
gnome-flashback/libscreensaver/Makefile.am | 3 +
gnome-flashback/libscreensaver/gf-listener.c | 585 ++++++++++++++++++++++++++
gnome-flashback/libscreensaver/gf-listener.h | 48 +++
3 files changed, 636 insertions(+), 0 deletions(-)
---
diff --git a/gnome-flashback/libscreensaver/Makefile.am b/gnome-flashback/libscreensaver/Makefile.am
index d46aafd..5cdb5f5 100644
--- a/gnome-flashback/libscreensaver/Makefile.am
+++ b/gnome-flashback/libscreensaver/Makefile.am
@@ -5,6 +5,7 @@ noinst_LTLIBRARIES = \
$(NULL)
libscreensaver_la_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"gf-screensaver\" \
-I$(top_builddir)/gnome-flashback/libscreensaver \
$(NULL)
@@ -15,6 +16,8 @@ libscreensaver_la_CFLAGS = \
$(NULL)
libscreensaver_la_SOURCES = \
+ gf-listener.c \
+ gf-listener.h \
gf-screensaver.c \
gf-screensaver.h \
$(BUILT_SOURCES) \
diff --git a/gnome-flashback/libscreensaver/gf-listener.c b/gnome-flashback/libscreensaver/gf-listener.c
new file mode 100644
index 0000000..2b015e4
--- /dev/null
+++ b/gnome-flashback/libscreensaver/gf-listener.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2004-2006 William Jon McCann
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * 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 3 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 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/>.
+ *
+ * Authors:
+ * Alberts Muktupāvels <alberts muktupavels gmail com>
+ * William Jon McCann <mccann jhu edu>
+ */
+
+#include "config.h"
+
+#include <time.h>
+
+#include "gf-listener.h"
+#include "gf-login-manager-gen.h"
+#include "gf-login-session-gen.h"
+#include "gf-screensaver-gen.h"
+
+#define SCREENSAVER_DBUS_NAME "org.gnome.ScreenSaver"
+#define SCREENSAVER_DBUS_PATH "/org/gnome/ScreenSaver"
+
+#define LOGIN_DBUS_NAME "org.freedesktop.login1"
+#define LOGIN_DBUS_PATH "/org/freedesktop/login1"
+#define LOGIN_SESSION_DBUS_PATH "/org/freedesktop/login1/session"
+
+struct _GfListener
+{
+ GObject parent;
+
+ GfScreensaverGen *screensaver;
+ guint screensaver_id;
+
+ guint login_id;
+ GfLoginSessionGen *login_session;
+ GfLoginManagerGen *login_manager;
+
+ gboolean enabled;
+
+ gboolean active;
+ time_t active_start;
+
+ gboolean idle;
+ time_t idle_start;
+};
+
+enum
+{
+ LOCK,
+ SHOW_MESSAGE,
+ SIMULATE_USER_ACTIVITY,
+
+ ACTIVE_CHANGED,
+
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GfListener, gf_listener, G_TYPE_OBJECT)
+
+static void
+set_idle_internal (GfListener *listener,
+ gboolean idle)
+{
+ listener->idle = idle;
+
+ if (idle)
+ {
+ listener->idle_start = time (NULL);
+ }
+ else
+ {
+ listener->idle_start = 0;
+ }
+}
+
+static gboolean
+handle_get_active_cb (GfScreensaverGen *object,
+ GDBusMethodInvocation *invocation,
+ GfListener *listener)
+{
+ gf_screensaver_gen_complete_get_active (object, invocation,
+ listener->active);
+
+ return TRUE;
+}
+
+static gboolean
+handle_get_active_time_cb (GfScreensaverGen *object,
+ GDBusMethodInvocation *invocation,
+ GfListener *listener)
+{
+ guint seconds;
+
+ if (listener->active)
+ {
+ time_t now;
+
+ now = time (NULL);
+
+ if (now < listener->active_start)
+ {
+ g_debug ("Active start time is in the future");
+ seconds = 0;
+ }
+ else if (listener->active_start <= 0)
+ {
+ g_debug ("Active start time was not set");
+ seconds = 0;
+ }
+ else
+ {
+ seconds = now - listener->active_start;
+ }
+ }
+ else
+ {
+ seconds = 0;
+ }
+
+ g_debug ("Screensaver active for %u seconds", seconds);
+ gf_screensaver_gen_complete_get_active_time (object, invocation, seconds);
+
+ return TRUE;
+}
+
+static gboolean
+handle_lock_cb (GfScreensaverGen *object,
+ GDBusMethodInvocation *invocation,
+ GfListener *listener)
+{
+ g_signal_emit (listener, signals[LOCK], 0);
+ gf_screensaver_gen_complete_lock (object, invocation);
+
+ return TRUE;
+}
+
+static gboolean
+handle_set_active_cb (GfScreensaverGen *object,
+ GDBusMethodInvocation *invocation,
+ gboolean active,
+ GfListener *listener)
+{
+ gf_listener_set_active (listener, active);
+ gf_screensaver_gen_complete_set_active (object, invocation);
+
+ return TRUE;
+}
+
+static gboolean
+handle_show_message_cb (GfScreensaverGen *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *summary,
+ const gchar *body,
+ const gchar *icon,
+ GfListener *listener)
+{
+ if (listener->active)
+ {
+ g_signal_emit (listener, signals[SHOW_MESSAGE], 0, summary, body, icon);
+ }
+
+ gf_screensaver_gen_complete_show_message (object, invocation);
+
+ return TRUE;
+}
+
+static gboolean
+handle_simulate_user_activity_cb (GfScreensaverGen *object,
+ GDBusMethodInvocation *invocation,
+ GfListener *listener)
+{
+ g_signal_emit (listener, signals[SIMULATE_USER_ACTIVITY], 0);
+ gf_screensaver_gen_complete_simulate_user_activity (object, invocation);
+
+ return TRUE;
+}
+
+static void
+bus_acquired_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GfListener *listener;
+ GDBusInterfaceSkeleton *skeleton;
+ GError *error;
+ gboolean exported;
+
+ listener = GF_LISTENER (user_data);
+ skeleton = G_DBUS_INTERFACE_SKELETON (listener->screensaver);
+
+ g_signal_connect (listener->screensaver, "handle-get-active",
+ G_CALLBACK (handle_get_active_cb), listener);
+ g_signal_connect (listener->screensaver, "handle-get-active-time",
+ G_CALLBACK (handle_get_active_time_cb), listener);
+ g_signal_connect (listener->screensaver, "handle-lock",
+ G_CALLBACK (handle_lock_cb), listener);
+ g_signal_connect (listener->screensaver, "handle-set-active",
+ G_CALLBACK (handle_set_active_cb), listener);
+ g_signal_connect (listener->screensaver, "handle-show-message",
+ G_CALLBACK (handle_show_message_cb), listener);
+ g_signal_connect (listener->screensaver, "handle-simulate-user-activity",
+ G_CALLBACK (handle_simulate_user_activity_cb), listener);
+
+ error = NULL;
+ exported = g_dbus_interface_skeleton_export (skeleton, connection,
+ SCREENSAVER_DBUS_PATH,
+ &error);
+
+ if (!exported)
+ {
+ g_warning ("Failed to export interface: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+}
+
+static void
+name_lost_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_warning ("Screensaver already running in this session");
+}
+
+static void
+lock_cb (GfLoginSessionGen *login_session,
+ GfListener *listener)
+{
+ g_debug ("Systemd requested session lock");
+ g_signal_emit (listener, signals[LOCK], 0);
+}
+
+static void
+unlock_cb (GfLoginSessionGen *login_session,
+ GfListener *listener)
+{
+ g_debug ("Systemd requested session unlock");
+ gf_listener_set_active (listener, FALSE);
+}
+
+static void
+notify_active_cb (GfLoginSessionGen *login_session,
+ GParamSpec *pspec,
+ GfListener *listener)
+{
+ if (gf_login_session_gen_get_active (login_session))
+ {
+ g_signal_emit (listener, signals[SIMULATE_USER_ACTIVITY], 0);
+ }
+}
+
+static void
+login_session_ready_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GfListener *listener;
+ GError *error;
+
+ listener = GF_LISTENER (user_data);
+
+ error = NULL;
+ listener->login_session = gf_login_session_gen_proxy_new_for_bus_finish (res, &error);
+
+ if (!listener->login_session)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ g_signal_connect (listener->login_session, "lock",
+ G_CALLBACK (lock_cb), listener);
+ g_signal_connect (listener->login_session, "unlock",
+ G_CALLBACK (unlock_cb), listener);
+
+ g_signal_connect (listener->login_session, "notify::active",
+ G_CALLBACK (notify_active_cb), listener);
+}
+
+static void
+prepare_for_sleep_cb (GfLoginManagerGen *login_manager,
+ GfListener *listener)
+{
+ g_debug ("A system suspend has been requested");
+ g_signal_emit (listener, signals[LOCK], 0);
+}
+
+static void
+login_manager_ready_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GfListener *listener;
+ GError *error;
+
+ listener = GF_LISTENER (user_data);
+
+ error = NULL;
+ listener->login_manager = gf_login_manager_gen_proxy_new_for_bus_finish (res, &error);
+
+ if (!listener->login_manager)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ g_signal_connect (listener->login_manager, "prepare-for-sleep",
+ G_CALLBACK (prepare_for_sleep_cb), listener);
+}
+
+static void
+name_appeared_handler (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ const gchar *xdg_session_id;
+ gchar *path;
+
+ xdg_session_id = g_getenv ("XDG_SESSION_ID");
+ if (!xdg_session_id || xdg_session_id[0] == '\0')
+ {
+ g_warning ("XDG_SESSION_ID environment variable is not set");
+ return;
+ }
+
+ path = g_strdup_printf ("%s/%s", LOGIN_SESSION_DBUS_PATH, xdg_session_id);
+
+ gf_login_session_gen_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ LOGIN_DBUS_NAME, path,
+ NULL, login_session_ready_cb,
+ user_data);
+
+ gf_login_manager_gen_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ LOGIN_DBUS_NAME, LOGIN_DBUS_PATH,
+ NULL, login_manager_ready_cb,
+ user_data);
+
+ g_free (path);
+}
+
+static void
+name_vanished_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GfListener *listener;
+
+ listener = GF_LISTENER (user_data);
+
+ g_clear_object (&listener->login_session);
+ g_clear_object (&listener->login_manager);
+}
+
+static void
+gf_listener_dispose (GObject *object)
+{
+ GfListener *listener;
+ GDBusInterfaceSkeleton *skeleton;
+
+ listener = GF_LISTENER (object);
+
+ if (listener->screensaver_id)
+ {
+ g_bus_unown_name (listener->screensaver_id);
+ listener->screensaver_id = 0;
+ }
+
+ if (listener->login_id)
+ {
+ g_bus_unwatch_name (listener->login_id);
+ listener->login_id = 0;
+ }
+
+ if (listener->screensaver)
+ {
+ skeleton = G_DBUS_INTERFACE_SKELETON (listener->screensaver);
+
+ g_dbus_interface_skeleton_unexport (skeleton);
+ g_clear_object (&listener->screensaver);
+ }
+
+ g_clear_object (&listener->login_session);
+ g_clear_object (&listener->login_manager);
+
+ G_OBJECT_CLASS (gf_listener_parent_class)->dispose (object);
+}
+
+static void
+install_signals (GObjectClass *object_class)
+{
+ signals[LOCK] =
+ g_signal_new ("lock", GF_TYPE_LISTENER, G_SIGNAL_RUN_LAST, 0, NULL,
+ NULL, NULL, G_TYPE_NONE, 0);
+
+ signals[SHOW_MESSAGE] =
+ g_signal_new ("show-message", GF_TYPE_LISTENER, G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING);
+
+ signals[SIMULATE_USER_ACTIVITY] =
+ g_signal_new ("simulate-user-activity", GF_TYPE_LISTENER,
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+ signals[ACTIVE_CHANGED] =
+ g_signal_new ("active-changed", GF_TYPE_LISTENER, G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+gf_listener_class_init (GfListenerClass *listener_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (listener_class);
+
+ object_class->dispose = gf_listener_dispose;
+
+ install_signals (object_class);
+}
+
+static void
+gf_listener_init (GfListener *listener)
+{
+ listener->screensaver = gf_screensaver_gen_skeleton_new ();
+ listener->screensaver_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ SCREENSAVER_DBUS_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ bus_acquired_handler, NULL,
+ name_lost_handler,
+ listener, NULL);
+
+ if (access("/run/systemd/seats/", F_OK) >= 0)
+ {
+ listener->login_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+ LOGIN_DBUS_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ name_appeared_handler,
+ name_vanished_handler,
+ listener, NULL);
+ }
+}
+
+GfListener *
+gf_listener_new (void)
+{
+ return g_object_new (GF_TYPE_LISTENER, NULL);
+}
+
+void
+gf_listener_set_enabled (GfListener *listener,
+ gboolean enabled)
+{
+ listener->enabled = enabled;
+}
+
+gboolean
+gf_listener_get_active (GfListener *listener)
+{
+ return listener->enabled;
+}
+
+gboolean
+gf_listener_set_active (GfListener *listener,
+ gboolean active)
+{
+ gboolean handled;
+
+ if (listener->active == active)
+ {
+ g_debug ("Trying to set active state when already: %s",
+ active ? "active" : "inactive");
+
+ return FALSE;
+ }
+
+ g_debug ("Setting active state: %s", active ? "active" : "inactive");
+
+ handled = FALSE;
+ g_signal_emit (listener, signals[ACTIVE_CHANGED], 0, active, &handled);
+
+ if (!handled)
+ {
+ /* if the signal is not handled then we haven't changed state */
+ g_debug ("active-changed signal not handled");
+
+ /* clear the idle state */
+ if (active)
+ {
+ set_idle_internal (listener, FALSE);
+ }
+
+ return FALSE;
+ }
+
+ listener->active = active;
+
+ /* if idle not in sync with active, change it */
+ if (listener->idle != active)
+ {
+ set_idle_internal (listener, active);
+ }
+
+ if (active)
+ {
+ listener->active_start = time (NULL);
+ }
+ else
+ {
+ listener->active_start = 0;
+ }
+
+ g_debug ("Sending the ActiveChanged(%s) signal on the session bus",
+ active ? "TRUE" : "FALSE");
+
+ if (listener->login_session)
+ {
+ gf_login_session_gen_call_set_locked_hint (listener->login_session,
+ active, NULL, NULL, NULL);
+ }
+
+ gf_screensaver_gen_emit_active_changed (listener->screensaver, active);
+
+ return TRUE;
+}
+
+gboolean
+gf_listener_set_idle (GfListener *listener,
+ gboolean idle)
+{
+ gboolean activated;
+
+ if (listener->idle == idle)
+ {
+ g_debug ("Trying to set idle state when already: %s",
+ idle ? "idle" : "not idle");
+
+ return FALSE;
+ }
+
+ g_debug ("Setting idle state: %s", idle ? "idle" : "not idle");
+
+ listener->idle = idle;
+ activated = TRUE;
+
+ if (listener->enabled && listener->idle)
+ {
+ g_debug ("Trying to activate");
+ activated = gf_listener_set_active (listener, TRUE);
+ }
+
+ /* if activation fails then don't set idle */
+ if (activated)
+ {
+ set_idle_internal (listener, idle);
+ }
+ else
+ {
+ g_debug ("Idle activation failed");
+ listener->idle = !idle;
+ }
+
+ return activated;
+}
diff --git a/gnome-flashback/libscreensaver/gf-listener.h b/gnome-flashback/libscreensaver/gf-listener.h
new file mode 100644
index 0000000..e6b8575
--- /dev/null
+++ b/gnome-flashback/libscreensaver/gf-listener.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2004-2006 William Jon McCann
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * 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 3 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 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/>.
+ *
+ * Authors:
+ * Alberts Muktupāvels <alberts muktupavels gmail com>
+ * William Jon McCann <mccann jhu edu>
+ */
+
+#ifndef GF_LISTENER_H
+#define GF_LISTENER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_LISTENER gf_listener_get_type ()
+G_DECLARE_FINAL_TYPE (GfListener, gf_listener, GF, LISTENER, GObject)
+
+GfListener *gf_listener_new (void);
+
+void gf_listener_set_enabled (GfListener *listener,
+ gboolean enabled);
+
+gboolean gf_listener_get_active (GfListener *listener);
+
+gboolean gf_listener_set_active (GfListener *listener,
+ gboolean active);
+
+gboolean gf_listener_set_idle (GfListener *listener,
+ gboolean idle);
+
+G_END_DECLS
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]