[gnome-flashback] screensaver: add GfWatcher



commit a77f309152a1eb1425138a6852abc07378cc2e48
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Mon Aug 1 04:21:41 2016 +0300

    screensaver: add GfWatcher

 gnome-flashback/libscreensaver/Makefile.am         |   15 +
 gnome-flashback/libscreensaver/gf-watcher.c        |  501 ++++++++++++++++++++
 gnome-flashback/libscreensaver/gf-watcher.h        |   49 ++
 .../org.gnome.SessionManager.Presence.xml          |   20 +
 4 files changed, 585 insertions(+), 0 deletions(-)
---
diff --git a/gnome-flashback/libscreensaver/Makefile.am b/gnome-flashback/libscreensaver/Makefile.am
index 3afd8ee..e4367eb 100644
--- a/gnome-flashback/libscreensaver/Makefile.am
+++ b/gnome-flashback/libscreensaver/Makefile.am
@@ -22,6 +22,8 @@ libscreensaver_la_SOURCES = \
        gf-screensaver.h \
        gf-settings.c \
        gf-settings.h \
+       gf-watcher.c \
+       gf-watcher.h \
        $(BUILT_SOURCES) \
        $(NULL)
 
@@ -64,6 +66,16 @@ gf-screensaver-gen.c: org.gnome.ScreenSaver.xml
                           "org.gtk.GDBus.C.Name" ScreensaverGen \
                $(srcdir)/org.gnome.ScreenSaver.xml
 
+gf-sm-presence-gen.h:
+gf-sm-presence-gen.c: org.gnome.SessionManager.Presence.xml
+       $(AM_V_GEN) $(GDBUS_CODEGEN) \
+               --interface-prefix org.gnome.SessionManager.Presence. \
+               --generate-c-code gf-sm-presence-gen \
+               --c-namespace Gf \
+               --annotate "org.gnome.SessionManager.Presence" \
+                          "org.gtk.GDBus.C.Name" SmPresenceGen \
+               $(srcdir)/org.gnome.SessionManager.Presence.xml
+
 BUILT_SOURCES = \
        gf-login-manager-gen.c \
        gf-login-manager-gen.h \
@@ -71,12 +83,15 @@ BUILT_SOURCES = \
        gf-login-session-gen.h \
        gf-screensaver-gen.c \
        gf-screensaver-gen.h \
+       gf-sm-presence-gen.c \
+       gf-sm-presence-gen.h \
        $(NULL)
 
 EXTRA_DIST = \
        org.freedesktop.login1.Manager.xml \
        org.freedesktop.login1.Session.xml \
        org.gnome.ScreenSaver.xml \
+       org.gnome.SessionManager.Presence.xml \
        $(NULL)
 
 CLEANFILES = \
diff --git a/gnome-flashback/libscreensaver/gf-watcher.c b/gnome-flashback/libscreensaver/gf-watcher.c
new file mode 100644
index 0000000..c692e0b
--- /dev/null
+++ b/gnome-flashback/libscreensaver/gf-watcher.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2004-2006 William Jon McCann
+ * Copyright (C) 2008 Red Hat, Inc.
+ * 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 <gdk/gdkx.h>
+
+#include "gf-sm-presence-gen.h"
+#include "gf-watcher.h"
+
+#define SESSION_MANAGER_DBUS_NAME "org.gnome.SessionManager"
+#define SESSION_MANAGER_PRESENCE_DBUS_PATH "/org/gnome/SessionManager/Presence"
+
+struct _GfWatcher
+{
+  GObject          parent;
+
+  guint            presence_id;
+  GfSmPresenceGen *presence;
+
+  gboolean         enabled;
+  gboolean         active;
+
+  gchar           *status_message;
+
+  gboolean         idle;
+  gboolean         idle_notice;
+  guint            idle_id;
+
+  guint            watchdog_id;
+};
+
+enum
+{
+  IDLE_CHANGED,
+  IDLE_NOTICE_CHANGED,
+
+  STATUS_MESSAGE_CHANGED,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GfWatcher, gf_watcher, G_TYPE_OBJECT)
+
+/* Figuring out what the appropriate XSetScreenSaver() parameters are
+ * (one wouldn't expect this to be rocket science.)
+ */
+static void
+disable_builtin_screensaver (GfWatcher *watcher,
+                             gboolean   unblank_screen)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  gint current_timeout;
+  gint current_interval;
+  gint prefer_blanking;
+  gint current_allow_exposures;
+  gint desired_timeout;
+  gint desired_interval;
+  gint desired_allow_exposures;
+
+  display = gdk_display_get_default ();
+  xdisplay = gdk_x11_display_get_xdisplay (display);
+
+  XGetScreenSaver (xdisplay, &current_timeout, &current_interval,
+                   &prefer_blanking, &current_allow_exposures);
+
+  /* When we're not using an extension, set the server-side timeout to 0,
+   * so that the server never gets involved with screen blanking, and we
+   * do it all ourselves.  (However, when we *are* using an extension, we
+   * tell the server when to notify us, and rather than blanking the screen,
+   * the server will send us an X event telling us to blank.)
+   */
+  desired_timeout = 0;
+
+  desired_interval = 0;
+
+  /* I suspect (but am not sure) that DontAllowExposures might have
+   * something to do with powering off the monitor as well, at least
+   * on some systems that don't support XDPMS? Who know...
+   */
+  desired_allow_exposures = AllowExposures;
+
+  if (desired_timeout != current_timeout ||
+      desired_interval != current_interval ||
+      desired_allow_exposures != current_allow_exposures)
+    {
+      g_debug ("Disabling server builtin screensaver:"
+               " (xset s %d %d; xset s %s; xset s %s)",
+               desired_timeout, desired_interval,
+               (prefer_blanking ? "blank" : "noblank"),
+               (desired_allow_exposures ? "expose" : "noexpose"));
+
+      XSetScreenSaver (xdisplay, desired_timeout, desired_interval,
+                       prefer_blanking, desired_allow_exposures);
+
+      XSync (xdisplay, FALSE);
+    }
+
+  if (unblank_screen)
+    {
+      /* Turn off the server builtin saver if it is now running. */
+      XForceScreenSaver (xdisplay, ScreenSaverReset);
+    }
+}
+
+/* Calls disable_builtin_screensaver() so that if xset has been used, or
+ * some other program (like xlock) has messed with the XSetScreenSaver()
+ * settings, they will be set back to sensible values (if a server
+ * extension is in use, messing with xlock can cause the screensaver to
+ * never get a wakeup event, and could cause monitor power-saving to occur,
+ * and all manner of heinousness.)
+ */
+static gboolean
+watchdog_cb (gpointer user_data)
+{
+  GfWatcher *watcher;
+
+  watcher = GF_WATCHER (user_data);
+
+  disable_builtin_screensaver (watcher, FALSE);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+set_session_idle (GfWatcher *watcher,
+                  gboolean   idle)
+{
+  gboolean handled;
+
+  if (watcher->idle == idle)
+    {
+      return FALSE;
+    }
+
+  handled = FALSE;
+  g_signal_emit (watcher, signals[IDLE_CHANGED], 0, idle, &handled);
+
+  if (handled)
+    {
+      g_debug ("Changing idle state: %d", idle);
+      watcher->idle = idle;
+    }
+  else
+    {
+      g_debug ("Signal idle-changed was not handled: %d", idle);
+    }
+
+  return handled;
+}
+
+static void
+set_session_idle_notice (GfWatcher *watcher,
+                         gboolean   idle_notice)
+{
+  gboolean handled;
+
+  if (watcher->idle_notice == idle_notice)
+    {
+      return;
+    }
+
+  handled = FALSE;
+  g_signal_emit (watcher, signals[IDLE_NOTICE_CHANGED], 0,
+                 idle_notice, &handled);
+
+  if (handled)
+    {
+      g_debug ("Changing idle notice state: %d", idle_notice);
+      watcher->idle_notice = idle_notice;
+    }
+  else
+    {
+      g_debug ("Signal idle-notice-changed was not handled: %d", idle_notice);
+    }
+}
+
+static gboolean
+idle_cb (gpointer user_data)
+{
+  GfWatcher *watcher;
+  gboolean res;
+
+  watcher = GF_WATCHER (user_data);
+  res = set_session_idle (watcher, TRUE);
+
+  set_session_idle_notice (watcher, FALSE);
+
+  if (res)
+    {
+      watcher->idle_id = 0;
+      return G_SOURCE_REMOVE;
+    }
+
+  /* try again if we failed i guess */
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+status_changed_cb (GfSmPresenceGen *presence,
+                   GfWatcher       *watcher)
+{
+  guint status;
+  gboolean idle;
+
+  if (!watcher->active)
+    {
+      g_debug ("Watcher not active, ignoring status changes");
+      return;
+    }
+
+  status = gf_sm_presence_gen_get_status (presence);
+  idle = (status == 3);
+
+  if (!idle && !watcher->idle_notice)
+    {
+      /* no change in idleness */
+      return;
+    }
+
+  if (watcher->idle_id > 0)
+    {
+      g_source_remove (watcher->idle_id);
+      watcher->idle_id = 0;
+    }
+
+  if (idle)
+    {
+      set_session_idle_notice (watcher, idle);
+
+      /* time before idle signal to send notice signal */
+      watcher->idle_id = g_timeout_add_seconds (10, idle_cb, watcher);
+    }
+  else
+    {
+      set_session_idle (watcher, FALSE);
+      set_session_idle_notice (watcher, FALSE);
+    }
+}
+
+static void
+status_text_changed_cb (GfSmPresenceGen *presence,
+                        GfWatcher       *watcher)
+{
+  const gchar *text;
+
+  text = gf_sm_presence_gen_get_status_text (presence);
+
+  g_free (watcher->status_message);
+  watcher->status_message = g_strdup (text);
+}
+
+static void
+presence_ready_cb (GObject      *object,
+                   GAsyncResult *res,
+                   gpointer      user_data)
+{
+  GfWatcher *watcher;
+  GError *error;
+
+  watcher = GF_WATCHER (user_data);
+
+  error = NULL;
+  watcher->presence = gf_sm_presence_gen_proxy_new_for_bus_finish (res, &error);
+
+  if (!watcher->presence)
+    {
+      g_warning ("%s", error->message);
+      g_error_free (error);
+
+      return;
+    }
+
+  g_signal_connect (watcher->presence, "status-changed",
+                    G_CALLBACK (status_changed_cb), watcher);
+  g_signal_connect (watcher->presence, "status-text-changed",
+                    G_CALLBACK (status_text_changed_cb), watcher);
+
+  status_changed_cb (watcher->presence, watcher);
+  status_text_changed_cb (watcher->presence, watcher);
+}
+
+static void
+name_appeared_handler (GDBusConnection *connection,
+                       const gchar     *name,
+                       const gchar     *name_owner,
+                       gpointer         user_data)
+{
+  gf_sm_presence_gen_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                        G_DBUS_PROXY_FLAGS_NONE,
+                                        SESSION_MANAGER_DBUS_NAME,
+                                        SESSION_MANAGER_PRESENCE_DBUS_PATH,
+                                        NULL, presence_ready_cb,
+                                        user_data);
+
+}
+
+static void
+name_vanished_handler (GDBusConnection *connection,
+                       const gchar     *name,
+                       gpointer         user_data)
+{
+  GfWatcher *watcher;
+
+  watcher = GF_WATCHER (user_data);
+
+  g_clear_object (&watcher->presence);
+}
+
+static void
+set_active_internal (GfWatcher *watcher,
+                     gboolean   active)
+{
+  if (watcher->active == active)
+    {
+      return;
+    }
+
+  watcher->idle = FALSE;
+  watcher->idle_notice = FALSE;
+  watcher->active = active;
+}
+
+static void
+gf_watcher_dispose (GObject *object)
+{
+  GfWatcher *watcher;
+
+  watcher = GF_WATCHER (object);
+
+  if (watcher->presence_id)
+    {
+      g_bus_unwatch_name (watcher->presence_id);
+      watcher->presence_id = 0;
+    }
+
+  if (watcher->idle_id > 0)
+    {
+      g_source_remove (watcher->idle_id);
+      watcher->idle_id = 0;
+    }
+
+  if (watcher->watchdog_id > 0)
+    {
+      g_source_remove (watcher->watchdog_id);
+      watcher->watchdog_id = 0;
+    }
+
+  g_clear_object (&watcher->presence);
+
+  G_OBJECT_CLASS (gf_watcher_parent_class)->dispose (object);
+}
+
+static void
+gf_watcher_finalize (GObject *object)
+{
+  GfWatcher *watcher;
+
+  watcher = GF_WATCHER (object);
+
+  g_free (watcher->status_message);
+
+  G_OBJECT_CLASS (gf_watcher_parent_class)->finalize (object);
+}
+
+static void
+install_signals (GObjectClass *object_class)
+{
+  signals[IDLE_CHANGED] =
+    g_signal_new ("idle-changed", GF_TYPE_WATCHER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+                  G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
+
+  signals[IDLE_NOTICE_CHANGED] =
+    g_signal_new ("idle-notice-changed", GF_TYPE_WATCHER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+                  G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
+
+  signals[STATUS_MESSAGE_CHANGED] =
+    g_signal_new ("status-message-changed", GF_TYPE_WATCHER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+}
+
+static void
+gf_watcher_class_init (GfWatcherClass *watcher_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (watcher_class);
+
+  object_class->dispose = gf_watcher_dispose;
+  object_class->finalize = gf_watcher_finalize;
+
+  install_signals (object_class);
+}
+
+static void
+gf_watcher_init (GfWatcher *watcher)
+{
+  watcher->enabled = TRUE;
+
+  watcher->presence_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                           SESSION_MANAGER_DBUS_NAME,
+                                           G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                           name_appeared_handler,
+                                           name_vanished_handler,
+                                           watcher, NULL);
+
+  /* This timer goes off every few minutes, whether the user is idle or
+   * not, to try and clean up anything that has gone wrong.
+   */
+  watcher->watchdog_id = g_timeout_add_seconds (600, watchdog_cb, watcher);
+}
+
+GfWatcher *
+gf_watcher_new (void)
+{
+  return g_object_new (GF_TYPE_WATCHER, NULL);
+}
+
+void
+gf_watcher_set_enabled (GfWatcher *watcher,
+                        gboolean   enabled)
+{
+  if (watcher->enabled == enabled)
+    {
+      return;
+    }
+
+  watcher->enabled = enabled;
+
+  if (!enabled && watcher->active)
+    {
+      set_active_internal (watcher, FALSE);
+    }
+}
+
+gboolean
+gf_watcher_get_enabled (GfWatcher *watcher)
+{
+  return watcher->enabled;
+}
+
+void
+gf_watcher_set_active (GfWatcher *watcher,
+                       gboolean   active)
+{
+  g_debug ("Turning watcher: %s", active ? "ON" : "OFF");
+
+  if (watcher->active == active)
+    {
+      g_debug ("Idle detection is already %s",
+               active ? "active" : "inactive");
+
+      return;
+    }
+
+  if (!watcher->enabled)
+    {
+      g_debug ("Idle detection is disabled, cannot activate");
+      return;
+    }
+
+  set_active_internal (watcher, active);
+}
+
+gboolean
+gf_watcher_get_active (GfWatcher *watcher)
+{
+  return watcher->active;
+}
+
+const gchar *
+gf_watcher_get_status_message (GfWatcher *watcher)
+{
+  return watcher->status_message;
+}
diff --git a/gnome-flashback/libscreensaver/gf-watcher.h b/gnome-flashback/libscreensaver/gf-watcher.h
new file mode 100644
index 0000000..44b7d53
--- /dev/null
+++ b/gnome-flashback/libscreensaver/gf-watcher.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004-2005 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_WATCHER_H
+#define GF_WATCHER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_WATCHER gf_watcher_get_type ()
+G_DECLARE_FINAL_TYPE (GfWatcher, gf_watcher, GF, WATCHER, GObject)
+
+GfWatcher   *gf_watcher_new                (void);
+
+void         gf_watcher_set_enabled        (GfWatcher *watcher,
+                                            gboolean   enabled);
+
+gboolean     gf_watcher_get_enabled        (GfWatcher *watcher);
+
+void         gf_watcher_set_active         (GfWatcher *watcher,
+                                            gboolean   active);
+
+gboolean     gf_watcher_get_active         (GfWatcher *watcher);
+
+const gchar *gf_watcher_get_status_message (GfWatcher *watcher);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libscreensaver/org.gnome.SessionManager.Presence.xml 
b/gnome-flashback/libscreensaver/org.gnome.SessionManager.Presence.xml
new file mode 100644
index 0000000..db89f4c
--- /dev/null
+++ b/gnome-flashback/libscreensaver/org.gnome.SessionManager.Presence.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node>
+  <interface name="org.gnome.SessionManager.Presence">
+
+    <property name="status" type="u" access="readwrite" />
+
+    <property name="status-text" type="s" access="readwrite" />
+
+    <signal name="StatusChanged">
+      <arg name="status" type="u" direction="in" />
+    </signal>
+
+    <signal name="StatusTextChanged">
+      <arg name="status_text" type="s" direction="in" />
+    </signal>
+
+  </interface>
+</node>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]