[drwright] Add Lock button to break window



commit 6ddc60f3493b7a77668431ea70b2db430ff3ed0e
Author: Christian Persch <chpe gnome org>
Date:   Sat Apr 16 23:55:22 2011 +0200

    Add Lock button to break window
    
    Based on a patch by Matthias Clasen.
    
    Bug #128381.

 src/drw-break-window.c |   96 ++++++++++++++++++++++++++++++++++++++++++-----
 src/drw-break-window.h |    2 +-
 src/drw-utils.c        |   13 ++++++
 src/drw-utils.h        |    3 +-
 src/drwright.c         |   97 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/drwright.h         |    2 +
 6 files changed, 198 insertions(+), 15 deletions(-)
---
diff --git a/src/drw-break-window.c b/src/drw-break-window.c
index 57d7a39..b2f5b07 100644
--- a/src/drw-break-window.c
+++ b/src/drw-break-window.c
@@ -22,6 +22,7 @@
 
 #include <config.h>
 #include <string.h>
+#include <unistd.h>
 #include <math.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
@@ -52,6 +53,8 @@ struct _DrwBreakWindowPrivate {
 	guint      postpone_delay;
 	gint       elapsed_idle_time;
 
+        gboolean   enable_lock;
+
 	GSettings *settings;
 };
 
@@ -67,11 +70,18 @@ struct _DrwBreakWindowPrivate {
 enum {
 	DONE,
 	POSTPONE,
+	LOCK,
 	LAST_SIGNAL
 };
 
+enum {
+        PROP_0,
+        PROP_ENABLE_LOCK
+};
+
 static void         drw_break_window_class_init    (DrwBreakWindowClass *klass);
 static void         drw_break_window_init          (DrwBreakWindow      *window);
+static void         drw_break_window_constructed   (GObject             *object);
 static void         drw_break_window_finalize      (GObject             *object);
 static void         drw_break_window_dispose       (GObject             *object);
 static gboolean     postpone_sensitize_cb          (DrwBreakWindow      *window);
@@ -84,10 +94,30 @@ G_DEFINE_TYPE (DrwBreakWindow, drw_break_window, GTK_TYPE_WINDOW)
 static guint signals[LAST_SIGNAL];
 
 static void
+drw_break_window_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+        DrwBreakWindow *window = DRW_BREAK_WINDOW (object);
+        DrwBreakWindowPrivate *priv = window->priv;
+
+        switch (property_id) {
+                case PROP_ENABLE_LOCK:
+                        priv->enable_lock = g_value_get_boolean (value);
+                        break;
+                default:
+                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        }
+}
+
+static void
 drw_break_window_class_init (DrwBreakWindowClass *klass)
 {
         GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+        object_class->set_property = drw_break_window_set_property;
+        object_class->constructed = drw_break_window_constructed;
         object_class->finalize = drw_break_window_finalize;
         object_class->dispose = drw_break_window_dispose;
 
@@ -100,6 +130,16 @@ drw_break_window_class_init (DrwBreakWindowClass *klass)
 			      g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE, 0);
 
+	signals[LOCK] =
+		g_signal_new ("lock",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
+	signals[DONE] =
 	signals[DONE] =
 		g_signal_new ("done",
 			      G_TYPE_FROM_CLASS (klass),
@@ -109,13 +149,35 @@ drw_break_window_class_init (DrwBreakWindowClass *klass)
 			      g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE, 0);
 
+        g_object_class_install_property
+                (object_class,
+                 PROP_ENABLE_LOCK,
+                 g_param_spec_boolean ("enable-lock", NULL, NULL,
+                                       FALSE,
+                                       G_PARAM_WRITABLE |
+                                       G_PARAM_CONSTRUCT_ONLY |
+                                       G_PARAM_STATIC_STRINGS));
+
 	g_type_class_add_private (klass, sizeof (DrwBreakWindowPrivate));
 }
 
 static void
+lock_clicked_cb (GtkWidget *button, DrwBreakWindow *window)
+{
+	g_signal_emit (window, signals[LOCK], 0, NULL);
+}
+
+static void
 drw_break_window_init (DrwBreakWindow *window)
 {
-	DrwBreakWindowPrivate *priv;
+        window->priv = DRW_BREAK_WINDOW_GET_PRIVATE (window);
+}
+
+static void
+drw_break_window_constructed (GObject *object)
+{
+        DrwBreakWindow        *window = DRW_BREAK_WINDOW (object);
+	DrwBreakWindowPrivate *priv = window->priv;
 	GtkWidget             *vbox;
 	GtkWidget             *hbox;
 	GtkWidget             *align;
@@ -124,6 +186,7 @@ drw_break_window_init (DrwBreakWindow *window)
 	GtkWidget             *outer_vbox;
 	GtkWidget             *button_box;
 	gboolean               allow_postpone;
+	GtkWidget             *lock_button;
 
 	gint                   root_monitor = 0;
 	GdkScreen             *screen = NULL;
@@ -131,8 +194,6 @@ drw_break_window_init (DrwBreakWindow *window)
 	gint                   right_padding;
 	gint                   bottom_padding;
 
-	priv = DRW_BREAK_WINDOW_GET_PRIVATE (window);
-	window->priv = priv;
 
         priv->settings = g_settings_new (DRW_SETTINGS_SCHEMA_ID);
 
@@ -180,12 +241,17 @@ drw_break_window_init (DrwBreakWindow *window)
 
 	gtk_box_pack_start (GTK_BOX (outer_vbox), align, TRUE, TRUE, 0);
 
-	if (allow_postpone) {
-		button_box = gtk_hbox_new (FALSE, 0);
-		gtk_widget_show (button_box);
+	if (allow_postpone || priv->enable_lock) {
+		button_box = gtk_hbutton_box_new ();
+                gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END);
+                gtk_container_set_border_width (GTK_CONTAINER (button_box), 12);
+                gtk_box_set_spacing (GTK_BOX (button_box), 12);
 
-		gtk_container_set_border_width (GTK_CONTAINER (button_box), 12);
+                gtk_box_pack_start (GTK_BOX (outer_vbox), button_box, FALSE, FALSE, 0);
+                gtk_widget_show (button_box);
+        }
 
+        if (allow_postpone) {
 		priv->postpone_button = gtk_button_new_with_mnemonic (_("_Postpone Break"));
                 gtk_button_set_focus_on_click (GTK_BUTTON (priv->postpone_button), FALSE);
 		gtk_widget_show (priv->postpone_button);
@@ -209,10 +275,18 @@ drw_break_window_init (DrwBreakWindow *window)
 		gtk_entry_set_has_frame (GTK_ENTRY (priv->postpone_entry), FALSE);
 
 		gtk_box_pack_end (GTK_BOX (button_box), priv->postpone_entry, FALSE, TRUE, 4);
-
-		gtk_box_pack_end (GTK_BOX (outer_vbox), button_box, FALSE, TRUE, 0);
 	}
 
+        if (priv->enable_lock) {
+                lock_button = gtk_button_new_with_mnemonic (_("_Lock Screen"));
+                gtk_widget_show (lock_button);
+                gtk_box_pack_start (GTK_BOX (button_box), lock_button, FALSE, FALSE, 0);
+                g_signal_connect (lock_button,
+                                  "clicked",
+                                  G_CALLBACK (lock_clicked_cb),
+                                  window);
+        }
+
 	vbox = gtk_vbox_new (FALSE, 0);
 	gtk_widget_show (vbox);
 
@@ -237,7 +311,6 @@ drw_break_window_init (DrwBreakWindow *window)
 
 	gtk_box_pack_start (GTK_BOX (hbox), priv->break_label, FALSE, FALSE, 12);
 
-
 	priv->clock_label = gtk_label_new (NULL);
 	gtk_misc_set_alignment (GTK_MISC (priv->clock_label), 0.5, 0.5);
 	gtk_widget_show (priv->clock_label);
@@ -310,7 +383,7 @@ drw_break_window_dispose (GObject *object)
 }
 
 GtkWidget *
-drw_break_window_new (void)
+drw_break_window_new (gboolean enable_lock)
 {
 	GObject *object;
 
@@ -319,6 +392,7 @@ drw_break_window_new (void)
 			       "skip-taskbar-hint", TRUE,
 			       "skip-pager-hint", TRUE,
 			       "focus-on-map", TRUE,
+                               "enable-lock", enable_lock,
 			       NULL);
 
 	return GTK_WIDGET (object);
diff --git a/src/drw-break-window.h b/src/drw-break-window.h
index b6b038b..78901d4 100644
--- a/src/drw-break-window.h
+++ b/src/drw-break-window.h
@@ -48,7 +48,7 @@ struct _DrwBreakWindowClass {
 };
 
 GType       drw_break_window_get_type (void) G_GNUC_CONST;
-GtkWidget * drw_break_window_new      (void);
+GtkWidget * drw_break_window_new      (gboolean can_lock);
 void        drw_break_window_set_elapsed_idle_time (DrwBreakWindow *window,
                                                     gint seconds);
 
diff --git a/src/drw-utils.c b/src/drw-utils.c
index 9242fa2..2e59959 100644
--- a/src/drw-utils.c
+++ b/src/drw-utils.c
@@ -19,6 +19,8 @@
  */
 
 #include <config.h>
+#include <unistd.h>
+#include <gio/gio.h>
 #include <gdk/gdk.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gtk/gtk.h>
@@ -222,3 +224,14 @@ drw_setup_background (GtkWidget *window)
 	}
 }
 
+static gboolean
+drw_is_program_in_path (const char *program)
+{
+	char *tmp = g_find_program_in_path (program);
+	if (tmp != NULL) {
+		g_free (tmp);
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
diff --git a/src/drw-utils.h b/src/drw-utils.h
index 9ef75bb..ea2693b 100644
--- a/src/drw-utils.h
+++ b/src/drw-utils.h
@@ -23,7 +23,6 @@
 
 #include <gtk/gtk.h>
 
-void drw_setup_background (GtkWidget *window);
-
+void     drw_setup_background (GtkWidget *window);
 
 #endif /* __DRW_UTILS_H__ */
diff --git a/src/drwright.c b/src/drwright.c
index c768c31..4eb1d98 100644
--- a/src/drwright.c
+++ b/src/drwright.c
@@ -53,6 +53,8 @@ typedef enum {
 struct _DrWright {
         GSettings      *settings;
 
+        GDBusProxy     *screensaver_proxy;
+
 	/* Widgets. */
 	GtkWidget      *break_window;
 	GList          *secondary_break_windows;
@@ -84,12 +86,55 @@ static void     break_window_done_cb           (GtkWidget      *window,
 						DrWright       *dr);
 static void     break_window_postpone_cb       (GtkWidget      *window,
 						DrWright       *dr);
+static void     break_window_lock_cb           (GtkWidget      *window,
+						DrWright       *dr);
 static void     break_window_destroy_cb        (GtkWidget      *window,
 						DrWright       *dr);
 static GList *  create_secondary_break_windows (void);
 
 extern gboolean debug;
 
+#define GNOME_SCREENSAVER_BUS_NAME      "org.gnome.ScreenSaver"
+#define GNOME_SCREENSAVER_OBJECT_PATH   "/org/gnome/ScreenSaver"
+#define GNOME_SCREENSAVER_INTERFACE     "org.gnome.ScreenSaver"
+
+/* FIXMEchpe: make this async! */
+static GDBusProxy *
+get_screensaver_proxy (DrWright *dr)
+{
+        GDBusConnection *connection;
+        GVariant *result;
+        GError *error = NULL;
+
+        if (dr->screensaver_proxy != NULL)
+                return dr->screensaver_proxy;
+
+        connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+        if (connection == NULL)
+                return NULL;
+
+        dr->screensaver_proxy =
+          g_dbus_proxy_new_sync (connection,
+                                 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+                                 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
+                                 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                 NULL,
+                                 GNOME_SCREENSAVER_BUS_NAME,
+                                 GNOME_SCREENSAVER_OBJECT_PATH,
+                                 GNOME_SCREENSAVER_INTERFACE,
+                                 NULL,
+                                 NULL);
+        g_object_unref (connection);
+
+        return dr->screensaver_proxy;
+}
+
+gboolean
+drwright_can_lock_screen (DrWright *dr)
+{
+        return get_screensaver_proxy (dr) != NULL;
+}
+
 static void
 notification_action_cb (NotifyNotification *notification,
                         const char *action,
@@ -304,7 +349,7 @@ maybe_change_state (DrWright *dr)
 
 		drw_timer_start (dr->timer);
 
-		dr->break_window = drw_break_window_new ();
+		dr->break_window = drw_break_window_new (drwright_can_lock_screen (dr));
 
 		drw_break_window_set_elapsed_idle_time (DRW_BREAK_WINDOW (dr->break_window),
 		                                        elapsed_idle_time);
@@ -324,6 +369,11 @@ maybe_change_state (DrWright *dr)
 				  dr);
 
 		g_signal_connect (dr->break_window,
+				  "lock",
+				  G_CALLBACK (break_window_lock_cb),
+				  dr);
+
+		g_signal_connect (dr->break_window,
 				  "destroy",
 				  G_CALLBACK (break_window_destroy_cb),
 				  dr);
@@ -427,6 +477,51 @@ break_window_postpone_cb (GtkWidget *window,
 }
 
 static void
+screensaver_locked_cb (GDBusProxy *proxy,
+                       GAsyncResult *result,
+                       DrWright *dr)
+{
+  GVariant *variant;
+
+  variant = g_dbus_proxy_call_finish (proxy, result, NULL);
+  if (variant == NULL)
+          return;
+
+  g_variant_unref (variant);
+
+  /* We keep the break window. If the user unlocks before the break is up,
+   * it'll still prevent typing; otherwise the timeout will have killed
+   * it in the meantime.
+   *
+   * FIXME: make sure we don't go to 'break' again while the screen is
+   * locked.
+   */
+}
+
+static void
+break_window_lock_cb (GtkWidget *window,
+		      DrWright  *dr)
+{
+        GDBusProxy *proxy;
+
+        proxy = get_screensaver_proxy (dr);
+        if (proxy == NULL)
+                return;
+
+        /* ungrab the keyboard so the screensaver can start */
+	gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+
+        g_dbus_proxy_call (proxy,
+                           "Lock",
+                           g_variant_new ("()"),
+                           G_DBUS_CALL_FLAGS_NONE,
+                           -1,
+                           NULL,
+                           (GAsyncReadyCallback) screensaver_locked_cb,
+                           dr);
+}
+
+static void
 break_window_destroy_cb (GtkWidget *window,
 			 DrWright  *dr)
 {
diff --git a/src/drwright.h b/src/drwright.h
index 9ce13c3..5481224 100644
--- a/src/drwright.h
+++ b/src/drwright.h
@@ -27,4 +27,6 @@ typedef struct _DrWright DrWright;
 
 DrWright *drwright_new (void);
 
+gboolean  drwright_can_lock_screen (DrWright *dr);
+
 #endif /* __DR_WRIGHT_H__ */



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