[gnome-flashback] screensaver: add GfWatcher
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] screensaver: add GfWatcher
- Date: Wed, 3 Aug 2016 23:06:36 +0000 (UTC)
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, ¤t_timeout, ¤t_interval,
+ &prefer_blanking, ¤t_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]