[Xfce4-commits] <xfce4-panel:devel> Refactor a lot of code in the clock plugin.

Nick Schermer noreply at xfce.org
Mon Sep 28 15:28:04 CEST 2009


Updating branch refs/heads/devel
         to db04e849bbcbc730562250a3df29d6704a251180 (commit)
       from 658534e0764998b5ea9b42920578f2059e673055 (commit)

commit db04e849bbcbc730562250a3df29d6704a251180
Author: Nick Schermer <nick at xfce.org>
Date:   Mon Sep 28 13:03:50 2009 +0200

    Refactor a lot of code in the clock plugin.
    
    Each clock widget now handles it's own timeout using a
    new automatic sync timeout function.
    
    Properly bind the properties using exo bindings for the
    dialog and xfconf bindings for the objects.
    
    Use g_timeout_add_seconds for all updates since we don't
    care about nano seconds and the seconds timeout stays
    much better in sync over time.

 plugins/clock/Makefile.am     |    2 +
 plugins/clock/clock-analog.c  |   67 ++--
 plugins/clock/clock-analog.h  |    6 +-
 plugins/clock/clock-binary.c  |   52 ++-
 plugins/clock/clock-binary.h  |    6 +-
 plugins/clock/clock-digital.c |   92 ++---
 plugins/clock/clock-digital.h |    6 +-
 plugins/clock/clock-fuzzy.c   |   63 ++--
 plugins/clock/clock-fuzzy.h   |    6 +-
 plugins/clock/clock-lcd.c     |   80 ++--
 plugins/clock/clock-lcd.h     |    4 -
 plugins/clock/clock.c         |  867 +++++++++++++++++++----------------------
 plugins/clock/clock.h         |   39 +-
 13 files changed, 619 insertions(+), 671 deletions(-)

diff --git a/plugins/clock/Makefile.am b/plugins/clock/Makefile.am
index 7d74427..360f1d7 100644
--- a/plugins/clock/Makefile.am
+++ b/plugins/clock/Makefile.am
@@ -35,6 +35,7 @@ libclock_la_CFLAGS = \
 	$(CAIRO_CFLAGS) \
 	$(LIBXFCE4UI_CFLAGS) \
 	$(PLATFORM_CFLAGS) \
+	$(EXO_CFLAGS) \
 	$(XFCONF_CFLAGS)
 
 libclock_la_LDFLAGS =	 \
@@ -51,6 +52,7 @@ libclock_la_LIBADD = \
 	$(CAIRO_LIBS) \
 	$(LIBXFCE4UTIL_LIBS) \
 	$(LIBXFCE4UI_LIBS) \
+	$(EXO_LIBS) \
 	$(XFCONF_LIBS)
 
 libclock_la_DEPENDENCIES = \
diff --git a/plugins/clock/clock-analog.c b/plugins/clock/clock-analog.c
index 83b6ea1..17d8953 100644
--- a/plugins/clock/clock-analog.c
+++ b/plugins/clock/clock-analog.c
@@ -34,17 +34,12 @@
 #include "clock.h"
 #include "clock-analog.h"
 
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
 #define CLOCK_SCALE 0.1
-#define TICKS_TO_RADIANS(x)   (M_PI - (M_PI / 30.0) * (x))
-#define HOURS_TO_RADIANS(x,y) (M_PI - (M_PI / 6.0) * (((x) > 12 ? (x) - 12 : (x)) + (y) / 60.0))
+#define TICKS_TO_RADIANS(x)   (G_PI - (G_PI / 30.0) * (x))
+#define HOURS_TO_RADIANS(x,y) (G_PI - (G_PI / 6.0) * (((x) > 12 ? (x) - 12 : (x)) + (y) / 60.0))
 
 
 
-/* prototypes */
 static void      xfce_clock_analog_set_property  (GObject              *object,
                                                   guint                 prop_id,
                                                   const GValue         *value,
@@ -53,8 +48,9 @@ static void      xfce_clock_analog_get_property  (GObject              *object,
                                                   guint                 prop_id,
                                                   GValue               *value,
                                                   GParamSpec           *pspec);
+static void      xfce_clock_analog_finalize      (GObject              *object);
 static void      xfce_clock_analog_size_request  (GtkWidget            *widget,
-                                            GtkRequisition       *requisition);
+                                                  GtkRequisition       *requisition);
 static gboolean  xfce_clock_analog_expose_event  (GtkWidget            *widget,
                                                   GdkEventExpose       *event);
 static void      xfce_clock_analog_draw_ticks    (cairo_t              *cr,
@@ -68,6 +64,7 @@ static void      xfce_clock_analog_draw_pointer  (cairo_t              *cr,
                                                   gdouble               angle,
                                                   gdouble               scale,
                                                   gboolean              line);
+static gboolean  xfce_clock_analog_update        (gpointer              user_data);
 
 
 
@@ -86,8 +83,9 @@ struct _XfceClockAnalog
 {
   GtkImage __parent__;
 
-    /* draw seconds */
-  guint show_seconds : 1;
+  ClockPluginTimeout *timeout;
+
+  guint               show_seconds : 1;
 };
 
 
@@ -105,6 +103,7 @@ xfce_clock_analog_class_init (XfceClockAnalogClass *klass)
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->set_property = xfce_clock_analog_set_property;
   gobject_class->get_property = xfce_clock_analog_get_property;
+  gobject_class->finalize = xfce_clock_analog_finalize;
 
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
   gtkwidget_class->size_request = xfce_clock_analog_size_request;
@@ -115,7 +114,7 @@ xfce_clock_analog_class_init (XfceClockAnalogClass *klass)
                                    g_param_spec_boolean ("show-seconds", NULL, NULL,
                                                          FALSE,
                                                          G_PARAM_READWRITE
-                                                         | G_PARAM_STATIC_BLURB));
+                                                         | G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -123,8 +122,10 @@ xfce_clock_analog_class_init (XfceClockAnalogClass *klass)
 static void
 xfce_clock_analog_init (XfceClockAnalog *analog)
 {
-  /* init */
   analog->show_seconds = FALSE;
+  analog->timeout = clock_plugin_timeout_new (CLOCK_INTERVAL_MINUTE,
+                                              xfce_clock_analog_update,
+                                              analog);
 }
 
 
@@ -147,6 +148,11 @@ xfce_clock_analog_set_property (GObject      *object,
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
     }
+
+  /* reschedule the timeout and redraw */
+  clock_plugin_timeout_set_interval (analog->timeout,
+      analog->show_seconds ? CLOCK_INTERVAL_SECOND : CLOCK_INTERVAL_MINUTE);
+  xfce_clock_analog_update (analog);
 }
 
 
@@ -174,6 +180,17 @@ xfce_clock_analog_get_property (GObject    *object,
 
 
 static void
+xfce_clock_analog_finalize (GObject *object)
+{
+  /* stop the timeout */
+  clock_plugin_timeout_free (XFCE_CLOCK_ANALOG (object)->timeout);
+
+  (*G_OBJECT_CLASS (xfce_clock_analog_parent_class)->finalize) (object);
+}
+
+
+
+static void
 xfce_clock_analog_size_request (GtkWidget      *widget,
                                 GtkRequisition *requisition)
 {
@@ -270,7 +287,7 @@ xfce_clock_analog_draw_ticks (cairo_t *cr,
 
       /* draw arc */
       cairo_move_to (cr, x, y);
-      cairo_arc (cr, x, y, radius * CLOCK_SCALE, 0, 2 * M_PI);
+      cairo_arc (cr, x, y, radius * CLOCK_SCALE, 0, 2 * G_PI);
       cairo_close_path (cr);
     }
 
@@ -308,12 +325,12 @@ xfce_clock_analog_draw_pointer (cairo_t *cr,
   else
     {
       /* calculate start position */
-      xs = xc + sin (angle - 0.5 * M_PI) * radius * CLOCK_SCALE;
-      ys = yc + cos (angle - 0.5 * M_PI) * radius * CLOCK_SCALE;
+      xs = xc + sin (angle - 0.5 * G_PI) * radius * CLOCK_SCALE;
+      ys = yc + cos (angle - 0.5 * G_PI) * radius * CLOCK_SCALE;
 
       /* draw the pointer */
       cairo_move_to (cr, xs, ys);
-      cairo_arc (cr, xc, yc, radius * CLOCK_SCALE, -angle + M_PI, -angle);
+      cairo_arc (cr, xc, yc, radius * CLOCK_SCALE, -angle + G_PI, -angle);
       cairo_line_to (cr, xt, yt);
       cairo_close_path (cr);
 
@@ -324,15 +341,7 @@ xfce_clock_analog_draw_pointer (cairo_t *cr,
 
 
 
-GtkWidget *
-xfce_clock_analog_new (void)
-{
-  return g_object_new (XFCE_CLOCK_TYPE_ANALOG, NULL);
-}
-
-
-
-gboolean
+static gboolean
 xfce_clock_analog_update (gpointer user_data)
 {
   GtkWidget *widget = GTK_WIDGET (user_data);
@@ -348,10 +357,8 @@ xfce_clock_analog_update (gpointer user_data)
 
 
 
-guint
-xfce_clock_analog_interval (XfceClockAnalog *analog)
+GtkWidget *
+xfce_clock_analog_new (void)
 {
-  panel_return_val_if_fail (XFCE_CLOCK_IS_ANALOG (analog), CLOCK_INTERVAL_SECOND);
-
-  return analog->show_seconds ? CLOCK_INTERVAL_SECOND : CLOCK_INTERVAL_MINUTE;
+  return g_object_new (XFCE_CLOCK_TYPE_ANALOG, NULL);
 }
diff --git a/plugins/clock/clock-analog.h b/plugins/clock/clock-analog.h
index 206aaf6..2be5da4 100644
--- a/plugins/clock/clock-analog.h
+++ b/plugins/clock/clock-analog.h
@@ -34,14 +34,10 @@ typedef struct _XfceClockAnalog      XfceClockAnalog;
 
 GType      xfce_clock_analog_get_type      (void) G_GNUC_CONST;
 
-void       xfce_clock_analog_register_type (GTypeModule     *type_module);
+void       xfce_clock_analog_register_type (GTypeModule *type_module);
 
 GtkWidget *xfce_clock_analog_new           (void) G_GNUC_MALLOC;
 
-gboolean   xfce_clock_analog_update        (gpointer         user_data);
-
-guint      xfce_clock_analog_interval      (XfceClockAnalog *analog);
-
 G_END_DECLS
 
 #endif /* !__CLOCK_ANALOG_H__ */
diff --git a/plugins/clock/clock-binary.c b/plugins/clock/clock-binary.c
index b94bbc1..e93db13 100644
--- a/plugins/clock/clock-binary.c
+++ b/plugins/clock/clock-binary.c
@@ -48,10 +48,13 @@ static void      xfce_clock_binary_get_property  (GObject              *object,
                                                   guint                 prop_id,
                                                   GValue               *value,
                                                   GParamSpec           *pspec);
+static void      xfce_clock_binary_finalize      (GObject              *object);
 static void      xfce_clock_binary_size_request  (GtkWidget            *widget,
-                                            GtkRequisition       *requisition);
+                                                  GtkRequisition       *requisition);
 static gboolean  xfce_clock_binary_expose_event  (GtkWidget            *widget,
                                                   GdkEventExpose       *event);
+static gboolean  xfce_clock_binary_update        (gpointer              user_data);
+
 
 
 enum
@@ -70,10 +73,9 @@ struct _XfceClockBinary
 {
   GtkImage  __parent__;
 
-  /* whether we draw seconds */
-  guint     show_seconds : 1;
+  ClockPluginTimeout *timeout;
 
-  /* if this is a true binary clock */
+  guint     show_seconds : 1;
   guint     true_binary : 1;
 };
 
@@ -92,6 +94,7 @@ xfce_clock_binary_class_init (XfceClockBinaryClass *klass)
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->set_property = xfce_clock_binary_set_property;
   gobject_class->get_property = xfce_clock_binary_get_property;
+  gobject_class->finalize = xfce_clock_binary_finalize;
 
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
   gtkwidget_class->size_request = xfce_clock_binary_size_request;
@@ -102,14 +105,14 @@ xfce_clock_binary_class_init (XfceClockBinaryClass *klass)
                                    g_param_spec_boolean ("show-seconds", NULL, NULL,
                                                          FALSE,
                                                          G_PARAM_READWRITE
-                                                         | G_PARAM_STATIC_BLURB));
+                                                         | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (gobject_class,
                                    PROP_TRUE_BINARY,
                                    g_param_spec_boolean ("true-binary", NULL, NULL,
                                                          FALSE,
                                                          G_PARAM_READWRITE
-                                                         | G_PARAM_STATIC_BLURB));
+                                                         | G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -120,6 +123,9 @@ xfce_clock_binary_init (XfceClockBinary *binary)
   /* init */
   binary->show_seconds = FALSE;
   binary->true_binary = FALSE;
+  binary->timeout = clock_plugin_timeout_new (CLOCK_INTERVAL_MINUTE,
+                                              xfce_clock_binary_update,
+                                              binary);
 }
 
 
@@ -146,6 +152,11 @@ xfce_clock_binary_set_property (GObject      *object,
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
     }
+
+  /* reschedule the timeout and resize */
+  clock_plugin_timeout_set_interval (binary->timeout,
+      binary->show_seconds ? CLOCK_INTERVAL_SECOND : CLOCK_INTERVAL_MINUTE);
+  gtk_widget_queue_resize (GTK_WIDGET (binary));
 }
 
 
@@ -177,6 +188,17 @@ xfce_clock_binary_get_property (GObject    *object,
 
 
 static void
+xfce_clock_binary_finalize (GObject *object)
+{
+  /* stop the timeout */
+  clock_plugin_timeout_free (XFCE_CLOCK_BINARY (object)->timeout);
+
+  (*G_OBJECT_CLASS (xfce_clock_binary_parent_class)->finalize) (object);
+}
+
+
+
+static void
 xfce_clock_binary_size_request (GtkWidget      *widget,
                                 GtkRequisition *requisition)
 {
@@ -336,15 +358,7 @@ xfce_clock_binary_expose_event (GtkWidget      *widget,
 
 
 
-GtkWidget *
-xfce_clock_binary_new (void)
-{
-  return g_object_new (XFCE_CLOCK_TYPE_BINARY, NULL);
-}
-
-
-
-gboolean
+static gboolean
 xfce_clock_binary_update (gpointer user_data)
 {
   GtkWidget *widget = GTK_WIDGET (user_data);
@@ -360,10 +374,8 @@ xfce_clock_binary_update (gpointer user_data)
 
 
 
-guint
-xfce_clock_binary_interval (XfceClockBinary *binary)
+GtkWidget *
+xfce_clock_binary_new (void)
 {
-  panel_return_val_if_fail (XFCE_CLOCK_IS_BINARY (binary), CLOCK_INTERVAL_SECOND);
-
-  return binary->show_seconds ? CLOCK_INTERVAL_SECOND : CLOCK_INTERVAL_MINUTE;
+  return g_object_new (XFCE_CLOCK_TYPE_BINARY, NULL);
 }
diff --git a/plugins/clock/clock-binary.h b/plugins/clock/clock-binary.h
index 9e14681..9aea508 100644
--- a/plugins/clock/clock-binary.h
+++ b/plugins/clock/clock-binary.h
@@ -34,14 +34,10 @@ typedef struct _XfceClockBinary      XfceClockBinary;
 
 GType      xfce_clock_binary_get_type      (void) G_GNUC_CONST;
 
-void       xfce_clock_binary_register_type (GTypeModule     *type_module);
+void       xfce_clock_binary_register_type (GTypeModule *type_module);
 
 GtkWidget *xfce_clock_binary_new           (void) G_GNUC_MALLOC;
 
-gboolean   xfce_clock_binary_update        (gpointer         user_data);
-
-guint      xfce_clock_binary_interval      (XfceClockBinary *binary);
-
 G_END_DECLS
 
 #endif /* !__CLOCK_BINARY_H__ */
diff --git a/plugins/clock/clock-digital.c b/plugins/clock/clock-digital.c
index 649433a..23f7d3d 100644
--- a/plugins/clock/clock-digital.c
+++ b/plugins/clock/clock-digital.c
@@ -30,17 +30,20 @@
 #include "clock.h"
 #include "clock-digital.h"
 
+#define DEFAULT_DIGITAL_FORMAT "%R"
 
 
-static void xfce_clock_digital_finalize     (GObject               *object);
-static void xfce_clock_digital_set_property (GObject               *object,
-                                             guint                  prop_id,
-                                             const GValue          *value,
-                                             GParamSpec            *pspec);
-static void xfce_clock_digital_get_property (GObject               *object,
-                                             guint                  prop_id,
-                                             GValue                *value,
-                                             GParamSpec            *pspec);
+
+static void     xfce_clock_digital_set_property (GObject               *object,
+                                                 guint                  prop_id,
+                                                 const GValue          *value,
+                                                 GParamSpec            *pspec);
+static void     xfce_clock_digital_get_property (GObject               *object,
+                                                 guint                  prop_id,
+                                                 GValue                *value,
+                                                 GParamSpec            *pspec);
+static void     xfce_clock_digital_finalize     (GObject               *object);
+static gboolean xfce_clock_digital_update       (gpointer               user_data);
 
 
 
@@ -59,7 +62,8 @@ struct _XfceClockDigital
 {
   GtkLabel __parent__;
 
-  /* clock format */
+  ClockPluginTimeout *timeout;
+
   gchar *format;
 };
 
@@ -82,9 +86,9 @@ xfce_clock_digital_class_init (XfceClockDigitalClass *klass)
   g_object_class_install_property (gobject_class,
                                    PROP_DIGITAL_FORMAT,
                                    g_param_spec_string ("digital-format", NULL, NULL,
-                                                        NULL,
+                                                        DEFAULT_DIGITAL_FORMAT,
                                                         G_PARAM_READWRITE
-                                                        | G_PARAM_STATIC_BLURB));
+                                                        | G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -92,29 +96,17 @@ xfce_clock_digital_class_init (XfceClockDigitalClass *klass)
 static void
 xfce_clock_digital_init (XfceClockDigital *digital)
 {
-  /* init */
-  digital->format = NULL;
+  digital->format = g_strdup (DEFAULT_DIGITAL_FORMAT);
+  digital->timeout = clock_plugin_timeout_new (clock_plugin_interval_from_format (digital->format),
+                                               xfce_clock_digital_update,
+                                               digital);
 
-  /* center text */
   gtk_label_set_justify (GTK_LABEL (digital), GTK_JUSTIFY_CENTER);
 }
 
 
 
 static void
-xfce_clock_digital_finalize (GObject *object)
-{
-  XfceClockDigital *digital = XFCE_CLOCK_DIGITAL (object);
-
-  /* cleanup */
-  g_free (digital->format);
-
-  (*G_OBJECT_CLASS (xfce_clock_digital_parent_class)->finalize) (object);
-}
-
-
-
-static void
 xfce_clock_digital_set_property (GObject      *object,
                                  guint         prop_id,
                                  const GValue *value,
@@ -125,20 +117,19 @@ xfce_clock_digital_set_property (GObject      *object,
   switch (prop_id)
     {
       case PROP_DIGITAL_FORMAT:
-        /* cleanup */
         g_free (digital->format);
-
-        /* set new format */
         digital->format = g_value_dup_string (value);
-
-        /* update the widget */
-        xfce_clock_digital_update (digital);
         break;
 
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
     }
+
+  /* reschedule the timeout and redraw */
+  clock_plugin_timeout_set_interval (digital->timeout,
+      clock_plugin_interval_from_format (digital->format));
+  xfce_clock_digital_update (digital);
 }
 
 
@@ -165,15 +156,22 @@ xfce_clock_digital_get_property (GObject    *object,
 
 
 
-GtkWidget *
-xfce_clock_digital_new (void)
+static void
+xfce_clock_digital_finalize (GObject *object)
 {
-  return g_object_new (XFCE_CLOCK_TYPE_DIGITAL, NULL);
+  XfceClockDigital *digital = XFCE_CLOCK_DIGITAL (object);
+
+  /* stop the timeout */
+  clock_plugin_timeout_free (digital->timeout);
+
+  g_free (digital->format);
+
+  (*G_OBJECT_CLASS (xfce_clock_digital_parent_class)->finalize) (object);
 }
 
 
 
-gboolean
+static gboolean
 xfce_clock_digital_update (gpointer user_data)
 {
   XfceClockDigital *digital = XFCE_CLOCK_DIGITAL (user_data);
@@ -185,14 +183,9 @@ xfce_clock_digital_update (gpointer user_data)
   /* get the local time */
   clock_plugin_get_localtime (&tm);
 
-  /* get the string */
-  string = clock_plugin_strdup_strftime (digital->format ? digital->format :
-                                         DEFAULT_DIGITAL_FORMAT, &tm);
-
-  /* set the new label */
+  /* set time string */
+  string = clock_plugin_strdup_strftime (digital->format, &tm);
   gtk_label_set_markup (GTK_LABEL (digital), string);
-
-  /* cleanup */
   g_free (string);
 
   return TRUE;
@@ -200,11 +193,8 @@ xfce_clock_digital_update (gpointer user_data)
 
 
 
-guint
-xfce_clock_digital_interval (XfceClockDigital *digital)
+GtkWidget *
+xfce_clock_digital_new (void)
 {
-  panel_return_val_if_fail (XFCE_CLOCK_IS_DIGITAL (digital), CLOCK_INTERVAL_SECOND);
-
-  return clock_plugin_interval_from_format (digital->format ? digital->format :
-                                            DEFAULT_DIGITAL_FORMAT);
+  return g_object_new (XFCE_CLOCK_TYPE_DIGITAL, NULL);
 }
diff --git a/plugins/clock/clock-digital.h b/plugins/clock/clock-digital.h
index 70c02b1..814f0f3 100644
--- a/plugins/clock/clock-digital.h
+++ b/plugins/clock/clock-digital.h
@@ -34,14 +34,10 @@ typedef struct _XfceClockDigital      XfceClockDigital;
 
 GType      xfce_clock_digital_get_type      (void) G_GNUC_CONST;
 
-void       xfce_clock_digital_register_type (GTypeModule      *type_module);
+void       xfce_clock_digital_register_type (GTypeModule *type_module);
 
 GtkWidget *xfce_clock_digital_new           (void) G_GNUC_MALLOC;
 
-gboolean   xfce_clock_digital_update        (gpointer          user_data);
-
-guint      xfce_clock_digital_interval      (XfceClockDigital *digital);
-
 G_END_DECLS
 
 #endif /* !__CLOCK_DIGITAL_H__ */
diff --git a/plugins/clock/clock-fuzzy.c b/plugins/clock/clock-fuzzy.c
index 6fa3ba0..6bb9899 100644
--- a/plugins/clock/clock-fuzzy.c
+++ b/plugins/clock/clock-fuzzy.c
@@ -32,14 +32,17 @@
 
 
 
-static void xfce_clock_fuzzy_set_property (GObject               *object,
-                                             guint                  prop_id,
-                                             const GValue          *value,
-                                             GParamSpec            *pspec);
-static void xfce_clock_fuzzy_get_property (GObject               *object,
-                                             guint                  prop_id,
-                                             GValue                *value,
-                                             GParamSpec            *pspec);
+static void     xfce_clock_fuzzy_set_property (GObject               *object,
+                                               guint                  prop_id,
+                                               const GValue          *value,
+                                               GParamSpec            *pspec);
+static void     xfce_clock_fuzzy_get_property (GObject               *object,
+                                               guint                  prop_id,
+                                               GValue                *value,
+                                               GParamSpec            *pspec);
+static void     xfce_clock_fuzzy_finalize     (GObject               *object);
+static gboolean xfce_clock_fuzzy_update       (gpointer               user_data);
+
 
 
 enum
@@ -68,8 +71,9 @@ struct _XfceClockFuzzy
 {
   GtkLabel __parent__;
 
-  /* fuzziness */
-  guint fuzziness;
+  ClockPluginTimeout *timeout;
+
+  guint               fuzziness;
 };
 
 const gchar *i18n_day_sectors[] =
@@ -114,14 +118,16 @@ xfce_clock_fuzzy_class_init (XfceClockFuzzyClass *klass)
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->set_property = xfce_clock_fuzzy_set_property;
   gobject_class->get_property = xfce_clock_fuzzy_get_property;
+  gobject_class->finalize = xfce_clock_fuzzy_finalize;
 
   g_object_class_install_property (gobject_class,
                                    PROP_FUZZINESS,
                                    g_param_spec_uint ("fuzziness", NULL, NULL,
-                                                      FUZZINESS_MIN, FUZZINESS_MAX,
+                                                      FUZZINESS_MIN,
+                                                      FUZZINESS_MAX,
                                                       FUZZINESS_DEFAULT,
                                                       G_PARAM_READWRITE
-                                                      | G_PARAM_STATIC_BLURB));
+                                                      | G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -129,10 +135,11 @@ xfce_clock_fuzzy_class_init (XfceClockFuzzyClass *klass)
 static void
 xfce_clock_fuzzy_init (XfceClockFuzzy *fuzzy)
 {
-  /* init */
   fuzzy->fuzziness = FUZZINESS_DEFAULT;
+  fuzzy->timeout = clock_plugin_timeout_new (CLOCK_INTERVAL_MINUTE,
+                                             xfce_clock_fuzzy_update,
+                                             fuzzy);
 
-  /* center text */
   gtk_label_set_justify (GTK_LABEL (fuzzy), GTK_JUSTIFY_CENTER);
 }
 
@@ -145,11 +152,17 @@ xfce_clock_fuzzy_set_property (GObject      *object,
                                GParamSpec   *pspec)
 {
   XfceClockFuzzy *fuzzy = XFCE_CLOCK_FUZZY (object);
+  guint           fuzziness;
 
   switch (prop_id)
     {
       case PROP_FUZZINESS:
-        fuzzy->fuzziness = MIN (g_value_get_uint (value), FUZZINESS_MAX);
+        fuzziness = g_value_get_uint (value);
+        if (G_LIKELY (fuzzy->fuzziness != fuzziness))
+          {
+            fuzzy->fuzziness = fuzziness;
+            xfce_clock_fuzzy_update (fuzzy);
+          }
         break;
 
       default:
@@ -182,15 +195,18 @@ xfce_clock_fuzzy_get_property (GObject    *object,
 
 
 
-GtkWidget *
-xfce_clock_fuzzy_new (void)
+static void
+xfce_clock_fuzzy_finalize (GObject *object)
 {
-  return g_object_new (XFCE_CLOCK_TYPE_FUZZY, NULL);
+  /* stop the timeout */
+  clock_plugin_timeout_free (XFCE_CLOCK_FUZZY (object)->timeout);
+
+  (*G_OBJECT_CLASS (xfce_clock_fuzzy_parent_class)->finalize) (object);
 }
 
 
 
-gboolean
+static gboolean
 xfce_clock_fuzzy_update (gpointer user_data)
 {
   XfceClockFuzzy *fuzzy = XFCE_CLOCK_FUZZY (user_data);
@@ -236,10 +252,9 @@ xfce_clock_fuzzy_update (gpointer user_data)
 
 
 
-guint
-xfce_clock_fuzzy_interval (XfceClockFuzzy *fuzzy)
-{
-  panel_return_val_if_fail (XFCE_CLOCK_IS_FUZZY (fuzzy), CLOCK_INTERVAL_MINUTE);
 
-  return CLOCK_INTERVAL_MINUTE;
+GtkWidget *
+xfce_clock_fuzzy_new (void)
+{
+  return g_object_new (XFCE_CLOCK_TYPE_FUZZY, NULL);
 }
diff --git a/plugins/clock/clock-fuzzy.h b/plugins/clock/clock-fuzzy.h
index ba4b7e3..7c308e0 100644
--- a/plugins/clock/clock-fuzzy.h
+++ b/plugins/clock/clock-fuzzy.h
@@ -34,14 +34,10 @@ typedef struct _XfceClockFuzzy      XfceClockFuzzy;
 
 GType      xfce_clock_fuzzy_get_type      (void) G_GNUC_CONST;
 
-void       xfce_clock_fuzzy_register_type (GTypeModule    *type_module);
+void       xfce_clock_fuzzy_register_type (GTypeModule *type_module);
 
 GtkWidget *xfce_clock_fuzzy_new           (void) G_GNUC_MALLOC;
 
-gboolean   xfce_clock_fuzzy_update        (gpointer        user_data);
-
-guint      xfce_clock_fuzzy_interval      (XfceClockFuzzy *fuzzy);
-
 G_END_DECLS
 
 #endif /* !__CLOCK_FUZZY_H__ */
diff --git a/plugins/clock/clock-lcd.c b/plugins/clock/clock-lcd.c
index 8f40f09..e0b5312 100644
--- a/plugins/clock/clock-lcd.c
+++ b/plugins/clock/clock-lcd.c
@@ -36,7 +36,7 @@
 #define RELATIVE_DOTS  (3 * RELATIVE_SPACE)
 
 
-/* prototypes */
+
 static void      xfce_clock_lcd_set_property (GObject           *object,
                                               guint              prop_id,
                                               const GValue      *value,
@@ -45,6 +45,7 @@ static void      xfce_clock_lcd_get_property (GObject           *object,
                                               guint              prop_id,
                                               GValue            *value,
                                               GParamSpec        *pspec);
+static void      xfce_clock_lcd_finalize     (GObject           *object);
 static void      xfce_clock_lcd_size_request (GtkWidget         *widget,
                                               GtkRequisition    *requisition);
 static gboolean  xfce_clock_lcd_expose_event (GtkWidget         *widget,
@@ -59,7 +60,7 @@ static gdouble   xfce_clock_lcd_draw_digit   (cairo_t           *cr,
                                               gdouble            size,
                                               gdouble            offset_x,
                                               gdouble            offset_y);
-
+static gboolean  xfce_clock_lcd_update       (gpointer           user_data);
 
 
 enum
@@ -80,17 +81,12 @@ struct _XfceClockLcd
 {
   GtkImage __parent__;
 
-  /* whether we show seconds */
-  guint    show_seconds : 1;
-
-  /* whether it's a 24h clock */
-  guint    show_military : 1;
-
-  /* whether we display am/pm */
-  guint    show_meridiem : 1;
+  ClockPluginTimeout *timeout;
 
-  /* whether to flash the separators */
-  guint    flash_separators : 1;
+  guint               show_seconds : 1;
+  guint               show_military : 1;
+  guint               show_meridiem : 1;
+  guint               flash_separators : 1;
 };
 
 
@@ -108,6 +104,7 @@ xfce_clock_lcd_class_init (XfceClockLcdClass *klass)
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->set_property = xfce_clock_lcd_set_property;
   gobject_class->get_property = xfce_clock_lcd_get_property;
+  gobject_class->finalize = xfce_clock_lcd_finalize;
 
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
   gtkwidget_class->size_request = xfce_clock_lcd_size_request;
@@ -121,7 +118,7 @@ xfce_clock_lcd_class_init (XfceClockLcdClass *klass)
                                    g_param_spec_boolean ("show-seconds", NULL, NULL,
                                                          FALSE,
                                                          G_PARAM_READWRITE
-                                                         | G_PARAM_STATIC_BLURB));
+                                                         | G_PARAM_STATIC_STRINGS));
 
   /**
    * Whether we show a 24h clock
@@ -131,7 +128,7 @@ xfce_clock_lcd_class_init (XfceClockLcdClass *klass)
                                    g_param_spec_boolean ("show-military", NULL, NULL,
                                                          FALSE,
                                                          G_PARAM_READWRITE
-                                                         | G_PARAM_STATIC_BLURB));
+                                                         | G_PARAM_STATIC_STRINGS));
 
   /**
    * Whether we show am or pm
@@ -141,7 +138,7 @@ xfce_clock_lcd_class_init (XfceClockLcdClass *klass)
                                    g_param_spec_boolean ("show-meridiem", NULL, NULL,
                                                          TRUE,
                                                          G_PARAM_READWRITE
-                                                         | G_PARAM_STATIC_BLURB));
+                                                         | G_PARAM_STATIC_STRINGS));
 
   /**
    * Whether to flash the time separators
@@ -151,7 +148,7 @@ xfce_clock_lcd_class_init (XfceClockLcdClass *klass)
                                    g_param_spec_boolean ("flash-separators", NULL, NULL,
                                                          FALSE,
                                                          G_PARAM_READWRITE
-                                                         | G_PARAM_STATIC_BLURB));
+                                                         | G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -159,11 +156,13 @@ xfce_clock_lcd_class_init (XfceClockLcdClass *klass)
 static void
 xfce_clock_lcd_init (XfceClockLcd *lcd)
 {
-  /* init */
   lcd->show_seconds = FALSE;
   lcd->show_meridiem = FALSE;
   lcd->show_military = TRUE;
   lcd->flash_separators = FALSE;
+  lcd->timeout = clock_plugin_timeout_new (CLOCK_INTERVAL_MINUTE,
+                                           xfce_clock_lcd_update,
+                                           lcd);
 }
 
 
@@ -175,6 +174,7 @@ xfce_clock_lcd_set_property (GObject      *object,
                              GParamSpec   *pspec)
 {
   XfceClockLcd *lcd = XFCE_CLOCK_LCD (object);
+  gboolean      show_seconds;
 
   switch (prop_id)
     {
@@ -198,6 +198,12 @@ xfce_clock_lcd_set_property (GObject      *object,
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
     }
+
+  /* reschedule the timeout and resize */
+  show_seconds = lcd->show_seconds || lcd->flash_separators;
+  clock_plugin_timeout_set_interval (lcd->timeout,
+      show_seconds ? CLOCK_INTERVAL_SECOND : CLOCK_INTERVAL_MINUTE);
+  gtk_widget_queue_resize (GTK_WIDGET (lcd));
 }
 
 
@@ -237,6 +243,17 @@ xfce_clock_lcd_get_property (GObject    *object,
 
 
 static void
+xfce_clock_lcd_finalize (GObject *object)
+{
+  /* stop the timeout */
+  clock_plugin_timeout_free (XFCE_CLOCK_LCD (object)->timeout);
+
+  (*G_OBJECT_CLASS (xfce_clock_lcd_parent_class)->finalize) (object);
+}
+
+
+
+static void
 xfce_clock_lcd_size_request (GtkWidget      *widget,
                              GtkRequisition *requisition)
 {
@@ -317,8 +334,12 @@ xfce_clock_lcd_expose_event (GtkWidget      *widget,
       if (!lcd->show_military && ticks > 12)
         ticks -= 12;
 
-      /* queue a resize when the number of hour digits changed */
-      if (G_UNLIKELY ((ticks == 10 || ticks == 0) && tm.tm_min == 0 && tm.tm_sec == 0))
+      /* queue a resize when the number of hour digits changed,
+       * because we might miss the exact second (due to slightly delayed
+       * timeout) we queue a resize the first 3 seconds or anything in
+       * the first minute */
+      if ((ticks == 10 || ticks == 0) && tm.tm_min == 0
+          && (!lcd->show_seconds || tm.tm_sec < 3))
         gtk_widget_queue_resize (widget);
 
       if (ticks >= 10)
@@ -542,15 +563,7 @@ xfce_clock_lcd_draw_digit (cairo_t *cr,
 
 
 
-GtkWidget *
-xfce_clock_lcd_new (void)
-{
-  return g_object_new (XFCE_CLOCK_TYPE_LCD, NULL);
-}
-
-
-
-gboolean
+static gboolean
 xfce_clock_lcd_update (gpointer user_data)
 {
   GtkWidget *widget = GTK_WIDGET (user_data);
@@ -566,13 +579,8 @@ xfce_clock_lcd_update (gpointer user_data)
 
 
 
-guint
-xfce_clock_lcd_interval (XfceClockLcd *lcd)
+GtkWidget *
+xfce_clock_lcd_new (void)
 {
-  panel_return_val_if_fail (XFCE_CLOCK_IS_LCD (lcd), CLOCK_INTERVAL_SECOND);
-
-  if (lcd->show_seconds || lcd->flash_separators)
-    return CLOCK_INTERVAL_SECOND;
-  else
-    return CLOCK_INTERVAL_MINUTE;
+  return g_object_new (XFCE_CLOCK_TYPE_LCD, NULL);
 }
diff --git a/plugins/clock/clock-lcd.h b/plugins/clock/clock-lcd.h
index f1bd8a6..8a71f1f 100644
--- a/plugins/clock/clock-lcd.h
+++ b/plugins/clock/clock-lcd.h
@@ -38,10 +38,6 @@ void       xfce_clock_lcd_register_type (GTypeModule  *type_module);
 
 GtkWidget *xfce_clock_lcd_new           (void) G_GNUC_MALLOC;
 
-gboolean   xfce_clock_lcd_update        (gpointer      user_data);
-
-guint      xfce_clock_lcd_interval      (XfceClockLcd *lcd);
-
 G_END_DECLS
 
 #endif /* !__CLOCK_LCD_H__ */
diff --git a/plugins/clock/clock.c b/plugins/clock/clock.c
index e96bd59..74df604 100644
--- a/plugins/clock/clock.c
+++ b/plugins/clock/clock.c
@@ -26,11 +26,12 @@
 #endif
 
 #include <gtk/gtk.h>
-#include <common/panel-private.h>
-#include <libxfce4panel/libxfce4panel.h>
+#include <exo/exo.h>
 #include <libxfce4ui/libxfce4ui.h>
-#include <xfconf/xfconf.h>
+#include <libxfce4panel/libxfce4panel.h>
+#include <common/panel-private.h>
 #include <common/panel-xfconf.h>
+#include <common/panel-builder.h>
 
 #include "clock.h"
 #include "clock-analog.h"
@@ -40,8 +41,18 @@
 #include "clock-lcd.h"
 #include "clock-dialog_ui.h"
 
+#define DEFAULT_TOOLTIP_FORMAT "%A %d %B %Y"
 
 
+
+static void     clock_plugin_get_property              (GObject               *object,
+                                                        guint                  prop_id,
+                                                        GValue                *value,
+                                                        GParamSpec            *pspec);
+static void     clock_plugin_set_property              (GObject               *object,
+                                                        guint                  prop_id,
+                                                        const GValue          *value,
+                                                        GParamSpec            *pspec);
 static gboolean clock_plugin_leave_notify_event        (GtkWidget             *widget,
                                                         GdkEventCrossing      *event);
 static gboolean clock_plugin_enter_notify_event        (GtkWidget             *widget,
@@ -52,28 +63,26 @@ static gboolean clock_plugin_size_changed              (XfcePanelPlugin       *p
                                                         gint                   size);
 static void     clock_plugin_orientation_changed       (XfcePanelPlugin       *panel_plugin,
                                                         GtkOrientation         orientation);
-static void     clock_plugin_save                      (XfcePanelPlugin       *panel_plugin);
 static void     clock_plugin_configure_plugin          (XfcePanelPlugin       *panel_plugin);
-static void     clock_plugin_property_changed          (XfconfChannel         *channel,
-                                                        const gchar           *property_name,
-                                                        const GValue          *value,
-                                                        ClockPlugin           *plugin);
-static void     clock_plugin_notify                    (GObject               *object,
-                                                        GParamSpec            *pspec,
-                                                        ClockPlugin           *plugin);
-static void     clock_plugin_set_child                 (ClockPlugin           *plugin);
-static gboolean clock_plugin_sync_timeout              (gpointer               user_data);
-static void     clock_plugin_sync                      (ClockPlugin           *plugin);
-static guint    clock_plugin_ms_to_next_interval       (guint                  timeout_interval);
-static gboolean clock_plugin_tooltip_timeout           (gpointer               user_data);
-static gboolean clock_plugin_tooltip_sync_timeout      (gpointer               user_data);
-static void     clock_plugin_tooltip_sync              (ClockPlugin           *plugin);
+
+static void     clock_plugin_set_mode                  (ClockPlugin           *plugin);
+static gboolean clock_plugin_tooltip                   (gpointer               user_data);
+static gboolean clock_plugin_timeout_running           (gpointer               user_data);
+static void     clock_plugin_timeout_destroyed         (gpointer               user_data);
+static gboolean clock_plugin_timeout_sync              (gpointer               user_data);
 
 
 
-enum _ClockPluginMode
+enum
+{
+  PROP_0,
+  PROP_MODE,
+  PROP_SHOW_FRAME,
+  PROP_TOOLTIP_FORMAT
+};
+
+typedef enum
 {
-  /* modes */
   CLOCK_PLUGIN_MODE_ANALOG = 0,
   CLOCK_PLUGIN_MODE_BINARY,
   CLOCK_PLUGIN_MODE_DIGITAL,
@@ -84,40 +93,42 @@ enum _ClockPluginMode
   CLOCK_PLUGIN_MODE_MIN = CLOCK_PLUGIN_MODE_ANALOG,
   CLOCK_PLUGIN_MODE_MAX = CLOCK_PLUGIN_MODE_LCD,
   CLOCK_PLUGIN_MODE_DEFAULT = CLOCK_PLUGIN_MODE_DIGITAL
-};
+}
+ClockPluginMode;
 
 struct _ClockPluginClass
 {
-  /* parent class */
   XfcePanelPluginClass __parent__;
 };
 
 struct _ClockPlugin
 {
-  /* parent type */
   XfcePanelPlugin __parent__;
 
-  /* xfconf channel */
-  XfconfChannel   *channel;
-
-  /* internal child widget */
-  GtkWidget       *clock;
-  GtkWidget       *frame;
+  GtkWidget          *clock;
+  GtkWidget          *frame;
 
-  /* clock widget update function and interval */
-  GSourceFunc      clock_func;
-  guint            clock_interval;
-  guint            clock_timeout_id;
+  ClockPluginMode     mode;
 
-  /* clock mode */
-  ClockPluginMode  mode;
+  gchar              *tooltip_format;
+  ClockPluginTimeout *tooltip_timeout;
+};
 
-  /* tooltip */
-  gchar           *tooltip_format;
-  guint            tooltip_timeout_id;
-  guint            tooltip_interval;
+struct _ClockPluginTimeout
+{
+  guint       interval;
+  GSourceFunc function;
+  gpointer    data;
+  guint       timeout_id;
 };
 
+typedef struct
+{
+  ClockPlugin *plugin;
+  GtkBuilder  *builder;
+}
+ClockPluginDialog;
+
 
 
 /* define the plugin */
@@ -133,9 +144,14 @@ XFCE_PANEL_DEFINE_PLUGIN (ClockPlugin, clock_plugin,
 static void
 clock_plugin_class_init (ClockPluginClass *klass)
 {
+  GObjectClass         *gobject_class;
   GtkWidgetClass       *widget_class;
   XfcePanelPluginClass *plugin_class;
 
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->set_property = clock_plugin_set_property;
+  gobject_class->get_property = clock_plugin_get_property;
+
   widget_class = GTK_WIDGET_CLASS (klass);
   widget_class->leave_notify_event = clock_plugin_leave_notify_event;
   widget_class->enter_notify_event = clock_plugin_enter_notify_event;
@@ -143,10 +159,32 @@ clock_plugin_class_init (ClockPluginClass *klass)
   plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
   plugin_class->construct = clock_plugin_construct;
   plugin_class->free_data = clock_plugin_free_data;
-  plugin_class->save = clock_plugin_save;
   plugin_class->size_changed = clock_plugin_size_changed;
   plugin_class->orientation_changed = clock_plugin_orientation_changed;
   plugin_class->configure_plugin = clock_plugin_configure_plugin;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_MODE,
+                                   g_param_spec_uint ("mode",
+                                                      NULL, NULL,
+                                                      CLOCK_PLUGIN_MODE_MIN,
+                                                      CLOCK_PLUGIN_MODE_MAX,
+                                                      CLOCK_PLUGIN_MODE_DEFAULT,
+                                                      EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_SHOW_FRAME,
+                                   g_param_spec_boolean ("show-frame",
+                                                         NULL, NULL,
+                                                         FALSE,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_TOOLTIP_FORMAT,
+                                   g_param_spec_string ("tooltip-format",
+                                                        NULL, NULL,
+                                                        DEFAULT_TOOLTIP_FORMAT,
+                                                        EXO_PARAM_READWRITE));
 }
 
 
@@ -154,15 +192,11 @@ clock_plugin_class_init (ClockPluginClass *klass)
 static void
 clock_plugin_init (ClockPlugin *plugin)
 {
-  /* init */
   plugin->mode = CLOCK_PLUGIN_MODE_DEFAULT;
   plugin->clock = NULL;
-  plugin->tooltip_format = NULL;
-  plugin->tooltip_timeout_id = 0;
-  plugin->tooltip_interval = 0;
-  plugin->clock_timeout_id = 0;
+  plugin->tooltip_format = g_strdup (DEFAULT_TOOLTIP_FORMAT);
+  plugin->tooltip_timeout = NULL;
 
-  /* create frame widget */
   plugin->frame = gtk_frame_new (NULL);
   gtk_container_add (GTK_CONTAINER (plugin), plugin->frame);
   gtk_widget_show (plugin->frame);
@@ -170,20 +204,85 @@ clock_plugin_init (ClockPlugin *plugin)
 
 
 
+static void
+clock_plugin_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  ClockPlugin   *plugin = XFCE_CLOCK_PLUGIN (object);
+  GtkShadowType  shadow_type;
+
+  switch (prop_id)
+    {
+      case PROP_MODE:
+        g_value_set_uint (value, plugin->mode);
+        break;
+
+      case PROP_SHOW_FRAME:
+        shadow_type = gtk_frame_get_shadow_type (GTK_FRAME (plugin->frame));
+        g_value_set_boolean (value, shadow_type == GTK_SHADOW_IN);
+        break;
+
+      case PROP_TOOLTIP_FORMAT:
+        g_value_set_string (value, plugin->tooltip_format);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+
+
+static void
+clock_plugin_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (object);
+
+  switch (prop_id)
+    {
+      case PROP_MODE:
+        if (plugin->mode != g_value_get_uint (value))
+          {
+            plugin->mode = g_value_get_uint (value);
+            clock_plugin_set_mode (plugin);
+          }
+        break;
+
+      case PROP_SHOW_FRAME:
+        gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame),
+            g_value_get_boolean (value) ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
+        break;
+
+      case PROP_TOOLTIP_FORMAT:
+        g_free (plugin->tooltip_format);
+        plugin->tooltip_format = g_value_dup_string (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+
+
 static gboolean
 clock_plugin_leave_notify_event (GtkWidget        *widget,
                                  GdkEventCrossing *event)
 {
-  ClockPlugin   *plugin = XFCE_CLOCK_PLUGIN (widget);
-  GtkAllocation *alloc = &widget->allocation;
+  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
 
   /* stop a running tooltip timeout when we leave the widget */
-  if (plugin->tooltip_timeout_id != 0
-      && (event->x <= 0 || event->x >= alloc->width
-          || event->y <= 0 || event->y >= alloc->height))
+  if (plugin->tooltip_timeout != NULL)
     {
-      g_source_remove (plugin->tooltip_timeout_id);
-      plugin->tooltip_timeout_id = 0;
+      clock_plugin_timeout_free (plugin->tooltip_timeout);
+      plugin->tooltip_timeout = NULL;
     }
 
   return FALSE;
@@ -196,10 +295,14 @@ clock_plugin_enter_notify_event (GtkWidget        *widget,
                                  GdkEventCrossing *event)
 {
   ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
+  guint        interval;
 
   /* start the tooltip timeout if needed */
-  if (plugin->tooltip_timeout_id == 0)
-    clock_plugin_tooltip_sync (plugin);
+  if (plugin->tooltip_timeout == NULL)
+    {
+      interval = clock_plugin_interval_from_format (plugin->tooltip_format);
+      plugin->tooltip_timeout = clock_plugin_timeout_new (interval, clock_plugin_tooltip, plugin);
+    }
 
   return FALSE;
 }
@@ -209,31 +312,26 @@ clock_plugin_enter_notify_event (GtkWidget        *widget,
 static void
 clock_plugin_construct (XfcePanelPlugin *panel_plugin)
 {
-  ClockPlugin   *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
-  gboolean       show_frame;
-  guint          mode;
+  ClockPlugin         *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
+  const PanelProperty  properties[] =
+  {
+    { "mode", G_TYPE_UINT },
+    { "show-frame", G_TYPE_BOOLEAN },
+    { "tooltip-format", G_TYPE_STRING },
+    { NULL }
+  };
 
   /* show configure */
-  xfce_panel_plugin_menu_show_configure (XFCE_PANEL_PLUGIN (plugin));
+  xfce_panel_plugin_menu_show_configure (panel_plugin);
 
-  /* set the xfconf channel */
-  plugin->channel = xfce_panel_plugin_xfconf_channel_new (panel_plugin);
-  g_signal_connect (G_OBJECT (plugin->channel), "property-changed",
-                    G_CALLBACK (clock_plugin_property_changed), plugin);
+  /* connect all properties */
+  panel_properties_bind (NULL, G_OBJECT (panel_plugin),
+                         xfce_panel_plugin_get_property_base (panel_plugin),
+                         properties, FALSE);
 
-  /* load properties */
-  mode = xfconf_channel_get_uint (plugin->channel, "/mode", CLOCK_PLUGIN_MODE_DEFAULT);
-  plugin->mode = MIN (mode, CLOCK_PLUGIN_MODE_MAX);
-
-  show_frame = xfconf_channel_get_bool (plugin->channel, "/show-frame", FALSE);
-  gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame), show_frame ? GTK_SHADOW_IN :
-                             GTK_SHADOW_NONE);
-
-  plugin->tooltip_format = xfconf_channel_get_string (plugin->channel, "/tooltip-format",
-                                                      DEFAULT_TOOLTIP_FORMAT);
-
-  /* create the clock widget */
-  clock_plugin_set_child (plugin);
+  /* make sure a mode is set */
+  if (plugin->mode == CLOCK_PLUGIN_MODE_DEFAULT)
+    clock_plugin_set_mode (plugin);
 }
 
 
@@ -243,20 +341,9 @@ clock_plugin_free_data (XfcePanelPlugin *panel_plugin)
 {
   ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
 
-  panel_return_if_fail (XFCONF_IS_CHANNEL (plugin->channel));
-
-  /* stop clock timeout */
-  if (plugin->clock_timeout_id != 0)
-    g_source_remove (plugin->clock_timeout_id);
+  if (plugin->tooltip_timeout != NULL)
+    clock_plugin_timeout_free (plugin->tooltip_timeout);
 
-  /* stop tooltip timeout */
-  if (plugin->tooltip_timeout_id != 0)
-    g_source_remove (plugin->tooltip_timeout_id);
-
-  /* release the xfonf channel */
-  g_object_unref (G_OBJECT (plugin->channel));
-
-  /* free the tooltip string */
   g_free (plugin->tooltip_format);
 }
 
@@ -269,6 +356,9 @@ clock_plugin_size_changed (XfcePanelPlugin *panel_plugin,
   ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
   gint         clock_size;
 
+  if (plugin->clock == NULL)
+    return TRUE;
+
   /* set the frame border */
   gtk_container_set_border_width (GTK_CONTAINER (plugin->frame), size > 26 ? 1 : 0);
 
@@ -297,493 +387,339 @@ clock_plugin_orientation_changed (XfcePanelPlugin *panel_plugin,
 
 
 static void
-clock_plugin_save (XfcePanelPlugin *panel_plugin)
+clock_plugin_configure_plugin_mode_changed (GtkComboBox       *combo,
+                                            ClockPluginDialog *dialog)
 {
-  ClockPlugin   *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
-  GtkShadowType  shadow_type;
-
-  panel_return_if_fail (XFCONF_IS_CHANNEL (plugin->channel));
-
-  /* shadow type */
-  shadow_type = gtk_frame_get_shadow_type (GTK_FRAME (plugin->frame));
-
-  /* save the properties */
-  xfconf_channel_set_uint (plugin->channel, "/mode", plugin->mode);
-  xfconf_channel_set_bool (plugin->channel, "/show-frame", !!(shadow_type == GTK_SHADOW_IN));
-  xfconf_channel_set_string (plugin->channel, "/tooltip-format", plugin->tooltip_format ?
-                             plugin->tooltip_format : "");
-}
-
-
-
-static void
-clock_plugin_configure_plugin_visibility (GtkComboBox *combo,
-                                          GtkBuilder  *builder)
-{
-  guint        i, visible = 0;
-  GObject     *object;
-  const gchar *names[] = { "show-seconds",     /* 1 */
-                           "true-binary",      /* 2 */
-                           "show-military",    /* 3 */
-                           "flash-separators", /* 4 */
-                           "show-meridiem",    /* 5 */
-                           "format-box",       /* 6 */
-                           "fuzziness-box"     /* 7 */};
+  guint     i, active, mode;
+  GObject *object;
+  struct {
+    const gchar *widget;
+    const gchar *binding;
+    const gchar *property;
+  } names[] = {
+    { "show-seconds", "show-seconds", "active" },
+    { "true-binary", "true-binary", "active" },
+    { "show-military", "show-military", "active" },
+    { "flash-separators", "flash-separators", "active" },
+    { "show-meridiem", "show-meridiem", "active" },
+    { "format-box", "digital-format", "active" },
+    { "fuzziness-box", "fuzziness", "value" }
+  };
 
   panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
-  panel_return_if_fail (GTK_IS_BUILDER (builder));
+  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
+  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (dialog->plugin));
 
-  /* the visible items for each mode */
-  switch (gtk_combo_box_get_active (combo))
+  /* the active items for each mode */
+  mode = gtk_combo_box_get_active (combo);
+  switch (mode)
     {
       case CLOCK_PLUGIN_MODE_ANALOG:
-        visible = 1 << 1;
+        active = 1 << 1;
         break;
 
       case CLOCK_PLUGIN_MODE_BINARY:
-        visible = 1 << 1 | 1 << 2;
+        active = 1 << 1 | 1 << 2;
         break;
 
       case CLOCK_PLUGIN_MODE_DIGITAL:
-        visible = 1 << 6;
+        active = 1 << 6;
         break;
 
       case CLOCK_PLUGIN_MODE_FUZZY:
-        visible = 1 << 7;
+        active = 1 << 7;
         break;
 
       case CLOCK_PLUGIN_MODE_LCD:
-        visible = 1 << 1 | 1 << 3 | 1 << 4 | 1 << 5;
+        active = 1 << 1 | 1 << 3 | 1 << 4 | 1 << 5;
         break;
     }
 
-  /* show or hide the widgets */
+  /* show or hide the dialog widgets */
   for (i = 0; i < G_N_ELEMENTS (names); i++)
     {
-      object = gtk_builder_get_object (builder, names[i]);
-      if (PANEL_HAS_FLAG (visible, 1 << (i + 1)))
+      object = gtk_builder_get_object (dialog->builder, names[i].widget);
+      panel_return_if_fail (G_IS_OBJECT (object));
+      if (PANEL_HAS_FLAG (active, 1 << (i + 1)))
         gtk_widget_show (GTK_WIDGET (object));
       else
         gtk_widget_hide (GTK_WIDGET (object));
     }
-}
-
-
-
-static void
-clock_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
-{
-  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
-  GtkBuilder  *builder;
-  GObject     *dialog;
-  GObject     *object;
 
-  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
-  panel_return_if_fail (XFCONF_IS_CHANNEL (plugin->channel));
-
-  /* save before we opend the dialog, so all properties exist in xfonf */
-  clock_plugin_save (panel_plugin);
+  /* make sure the new mode is set */
+  if (dialog->plugin->mode != mode)
+    g_object_set (G_OBJECT (dialog->plugin), "mode", mode, NULL);
+  panel_return_if_fail (G_IS_OBJECT (dialog->plugin->clock));
 
-  /* load the dialog from the ui file */
-  builder = gtk_builder_new ();
-  if (gtk_builder_add_from_string (builder, clock_dialog_ui, clock_dialog_ui_length, NULL))
-    {
-      dialog = gtk_builder_get_object (builder, "dialog");
-      g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_object_unref, builder);
-      xfce_panel_plugin_take_window (panel_plugin, GTK_WINDOW (dialog));
-
-      xfce_panel_plugin_block_menu (panel_plugin);
-      g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) xfce_panel_plugin_unblock_menu, panel_plugin);
-
-      object = gtk_builder_get_object (builder, "close-button");
-      g_signal_connect_swapped (G_OBJECT (object), "clicked", G_CALLBACK (gtk_widget_destroy), dialog);
-
-      object = gtk_builder_get_object (builder, "mode");
-      g_signal_connect (G_OBJECT (object), "changed", G_CALLBACK (clock_plugin_configure_plugin_visibility), builder);
-
-      #define create_binding(property, type, name) \
-        object = gtk_builder_get_object (builder, property); \
-        panel_return_if_fail (G_IS_OBJECT (object)); \
-        xfconf_g_property_bind (plugin->channel, "/" property, type, object, name)
-
-      /* create bindings */
-      create_binding ("mode", G_TYPE_UINT, "active");
-      create_binding ("show-frame", G_TYPE_BOOLEAN, "active");
-      create_binding ("show-seconds", G_TYPE_BOOLEAN, "active");
-      create_binding ("true-binary", G_TYPE_BOOLEAN, "active");
-      create_binding ("show-military", G_TYPE_BOOLEAN, "active");
-      create_binding ("flash-separators", G_TYPE_BOOLEAN, "active");
-      create_binding ("show-meridiem", G_TYPE_BOOLEAN, "active");
-      create_binding ("fuzziness", G_TYPE_UINT, "value");
-
-      gtk_widget_show (GTK_WIDGET (dialog));
-    }
-  else
+  /* connect the exo bindings */
+  for (i = 0; i < G_N_ELEMENTS (names); i++)
     {
-      /* release the builder */
-      g_object_unref (G_OBJECT (builder));
+      if (PANEL_HAS_FLAG (active, 1 << (i + 1)))
+        {
+          object = gtk_builder_get_object (dialog->builder, names[i].binding);
+          panel_return_if_fail (G_IS_OBJECT (object));
+          exo_mutual_binding_new (G_OBJECT (dialog->plugin->clock), names[i].binding,
+                                  G_OBJECT (object), names[i].property);
+        }
     }
 }
 
 
 
 static void
-clock_plugin_property_changed (XfconfChannel *channel,
-                               const gchar   *property_name,
-                               const GValue  *value,
-                               ClockPlugin   *plugin)
+clock_plugin_configure_plugin_free (gpointer  user_data,
+                                    GObject  *where_the_object_was)
 {
-  panel_return_if_fail (XFCONF_IS_CHANNEL (channel));
-  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
-  panel_return_if_fail (plugin->channel == channel);
-
-  if (strcmp (property_name, "/mode") == 0)
-    {
-      /* set new clock mode */
-      plugin->mode = MIN (g_value_get_uint (value), CLOCK_PLUGIN_MODE_MAX);
-
-      /* update the child widget */
-      clock_plugin_set_child (plugin);
-    }
-  else if (strcmp (property_name, "/tooltip-format") == 0)
-    {
-      /* cleanup */
-      g_free (plugin->tooltip_format);
-
-      /* set new tooltip */
-      plugin->tooltip_format = g_value_dup_string (value);
-
-      /* update the tooltip if a timeout is running */
-      if (plugin->tooltip_timeout_id != 0)
-        clock_plugin_tooltip_sync (plugin);
-    }
-  else if (strcmp (property_name, "/show-frame") == 0)
-    {
-      /* update frame shadow */
-      gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame),
-                                 g_value_get_boolean (value) ? GTK_SHADOW_IN :
-                                 GTK_SHADOW_NONE);
-    }
+  g_slice_free (ClockPluginDialog, user_data);
 }
 
 
 
 static void
-clock_plugin_notify (GObject     *object,
-                     GParamSpec  *pspec,
-                     ClockPlugin *plugin)
+clock_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
 {
+  ClockPlugin       *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
+  ClockPluginDialog *dialog;
+  GtkBuilder        *builder;
+  GObject           *window;
+  GObject           *object;
+
   panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
-  panel_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
-  /* bit of an ugly hack, but it works */
-  if (g_param_spec_get_blurb (pspec) == NULL)
-    {
-      gtk_widget_queue_resize (plugin->clock);
-      clock_plugin_sync (plugin);
-    }
+  /* setup the dialog */
+  builder = panel_builder_new (panel_plugin, clock_dialog_ui,
+                               clock_dialog_ui_length, &window);
+  if (G_UNLIKELY (builder == NULL))
+    return;
+
+  dialog = g_slice_new0 (ClockPluginDialog);
+  dialog->plugin = plugin;
+  dialog->builder = builder;
+  g_object_weak_ref (G_OBJECT (builder), clock_plugin_configure_plugin_free, dialog);
+
+  object = gtk_builder_get_object (builder, "mode");
+  g_signal_connect (G_OBJECT (object), "changed",
+      G_CALLBACK (clock_plugin_configure_plugin_mode_changed), dialog);
+  exo_mutual_binding_new (G_OBJECT (plugin), "mode",
+                          G_OBJECT (object), "active");
+
+  object = gtk_builder_get_object (builder, "show-frame");
+  exo_mutual_binding_new (G_OBJECT (plugin), "show-frame",
+                          G_OBJECT (object), "active");
+
+  gtk_widget_show (GTK_WIDGET (window));
 }
 
 
 
 static void
-clock_plugin_set_child (ClockPlugin *plugin)
+clock_plugin_set_mode (ClockPlugin *plugin)
 {
-  gint width = -1, height = -1;
+  const PanelProperty properties[][5] =
+  {
+    { /* analog */
+      { "show-seconds", G_TYPE_BOOLEAN },
+      { NULL },
+    },
+    { /* binary */
+      { "show-seconds", G_TYPE_BOOLEAN },
+      { "true-binary", G_TYPE_BOOLEAN },
+      { NULL },
+    },
+    { /* digital */
+      { "digital-format", G_TYPE_STRING },
+      { NULL },
+    },
+    { /* fuzzy */
+      { "fuzziness", G_TYPE_UINT },
+      { NULL },
+    },
+    { /* lcd */
+      { "show-seconds", G_TYPE_BOOLEAN },
+      { "show-military", G_TYPE_BOOLEAN },
+      { "show-meridiem", G_TYPE_BOOLEAN },
+      { "flash-separators", G_TYPE_BOOLEAN },
+      { NULL },
+    }
+  };
 
   panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
-  panel_return_if_fail (XFCONF_IS_CHANNEL (plugin->channel));
-
-  /* stop running timeout */
-  if (plugin->clock_timeout_id != 0)
-    {
-      g_source_remove (plugin->clock_timeout_id);
-      plugin->clock_timeout_id = 0;
-    }
 
-  /* destroy the child */
-  if (plugin->clock)
-    {
-      gtk_widget_get_size_request (plugin->clock, &width, &height);
-      gtk_widget_destroy (GTK_WIDGET (plugin->clock));
-      plugin->clock = NULL;
-    }
+  if (plugin->clock != NULL)
+    gtk_widget_destroy (plugin->clock);
 
   /* create a new clock */
-  switch (plugin->mode)
-    {
-      case CLOCK_PLUGIN_MODE_ANALOG:
-        /* create widget */
-        plugin->clock = xfce_clock_analog_new ();
-        plugin->clock_func = xfce_clock_analog_update;
-
-        /* connect binding */
-        xfconf_g_property_bind (plugin->channel, "/show-seconds",
-                                G_TYPE_BOOLEAN, plugin->clock,
-                                "show-seconds");
-        break;
-
-      case CLOCK_PLUGIN_MODE_BINARY:
-        /* create widget */
-        plugin->clock = xfce_clock_binary_new ();
-        plugin->clock_func = xfce_clock_binary_update;
-
-        /* connect bindings */
-        xfconf_g_property_bind (plugin->channel, "/show-seconds",
-                                G_TYPE_BOOLEAN, plugin->clock,
-                                "show-seconds");
-        xfconf_g_property_bind (plugin->channel, "/true-binary",
-                                G_TYPE_BOOLEAN, plugin->clock,
-                                "true-binary");
-        break;
-
-      case CLOCK_PLUGIN_MODE_DIGITAL:
-        /* create widget */
-        plugin->clock = xfce_clock_digital_new ();
-        plugin->clock_func = xfce_clock_digital_update;
-
-        /* connect binding */
-        xfconf_g_property_bind (plugin->channel, "/digital-format",
-                                G_TYPE_STRING, plugin->clock,
-                                "digital-format");
-        break;
-
-      case CLOCK_PLUGIN_MODE_FUZZY:
-        /* create widget */
-        plugin->clock = xfce_clock_fuzzy_new ();
-        plugin->clock_func = xfce_clock_fuzzy_update;
-
-        /* connect binding */
-        xfconf_g_property_bind (plugin->channel, "/fuzziness",
-                                G_TYPE_UINT, plugin->clock,
-                                "fuzziness");
-        break;
+  if (plugin->mode == CLOCK_PLUGIN_MODE_ANALOG)
+    plugin->clock = xfce_clock_analog_new ();
+  else if (plugin->mode == CLOCK_PLUGIN_MODE_BINARY)
+    plugin->clock = xfce_clock_binary_new ();
+  else if (plugin->mode == CLOCK_PLUGIN_MODE_DIGITAL)
+    plugin->clock = xfce_clock_digital_new ();
+  else if (plugin->mode == CLOCK_PLUGIN_MODE_FUZZY)
+    plugin->clock = xfce_clock_fuzzy_new ();
+  else
+    plugin->clock = xfce_clock_lcd_new ();
 
-      case CLOCK_PLUGIN_MODE_LCD:
-        /* create widget */
-        plugin->clock = xfce_clock_lcd_new ();
-        plugin->clock_func = xfce_clock_lcd_update;
-
-        /* connect bindings */
-        xfconf_g_property_bind (plugin->channel, "/show-seconds",
-                                G_TYPE_BOOLEAN, plugin->clock,
-                                "show-seconds");
-        xfconf_g_property_bind (plugin->channel, "/show-military",
-                                G_TYPE_BOOLEAN, plugin->clock,
-                                "show-military");
-        xfconf_g_property_bind (plugin->channel, "/show-meridiem",
-                                G_TYPE_BOOLEAN, plugin->clock,
-                                "show-meridiem");
-        xfconf_g_property_bind (plugin->channel, "/flash-separators",
-                                G_TYPE_BOOLEAN, plugin->clock,
-                                "flash-separators");
-        break;
-    }
+  panel_properties_bind (NULL, G_OBJECT (plugin->clock),
+                         xfce_panel_plugin_get_property_base (XFCE_PANEL_PLUGIN (plugin)),
+                         properties[plugin->mode], FALSE);
 
-  /* add the widget to the plugin frame */
   gtk_container_add (GTK_CONTAINER (plugin->frame), plugin->clock);
-  gtk_widget_set_size_request (plugin->clock, width, height);
+  clock_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
+      xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
   gtk_widget_show (plugin->clock);
-
-  /* start clock timeout */
-  clock_plugin_sync (plugin);
-
-  /* property notify */
-  g_signal_connect (G_OBJECT (plugin->clock), "notify", G_CALLBACK (clock_plugin_notify), plugin);
 }
 
 
 
 static gboolean
-clock_plugin_sync_timeout (gpointer user_data)
+clock_plugin_tooltip (gpointer user_data)
 {
   ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (user_data);
+  gchar       *string;
+  struct tm    tm;
 
-  panel_return_val_if_fail (GTK_IS_WIDGET (plugin->clock), FALSE);
+  /* get the local time */
+  clock_plugin_get_localtime (&tm);
 
-  /* start the clock update timeout */
-  plugin->clock_timeout_id = g_timeout_add (plugin->clock_interval,
-                                            plugin->clock_func,
-                                            plugin->clock);
+  /* set the tooltip */
+  string = clock_plugin_strdup_strftime (plugin->tooltip_format, &tm);
+  gtk_widget_set_tooltip_text (GTK_WIDGET (plugin), string);
+  g_free (string);
 
-  /* manual update for this interval */
-  (plugin->clock_func) (plugin->clock);
+  /* make sure the tooltip is up2date */
+  gtk_widget_trigger_tooltip_query (GTK_WIDGET (plugin));
 
-  /* stop the sync timeout */
-  return FALSE;
+  /* keep the timeout running */
+  return TRUE;
 }
 
 
 
-static void
-clock_plugin_sync (ClockPlugin *plugin)
+static gboolean
+clock_plugin_timeout_running (gpointer user_data)
 {
-  guint interval;
+  ClockPluginTimeout *timeout = user_data;
 
-  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
-
-  /* stop a running timeout */
-  if (plugin->clock_timeout_id != 0)
-    {
-      g_source_remove (plugin->clock_timeout_id);
-      plugin->clock_timeout_id = 0;
-    }
-
-  if (plugin->clock)
-    {
-      /* get the timeout interval */
-      switch (plugin->mode)
-        {
-          case CLOCK_PLUGIN_MODE_ANALOG:
-            plugin->clock_interval = xfce_clock_analog_interval (XFCE_CLOCK_ANALOG (plugin->clock));
-            break;
-
-          case CLOCK_PLUGIN_MODE_BINARY:
-            plugin->clock_interval = xfce_clock_binary_interval (XFCE_CLOCK_BINARY (plugin->clock));
-            break;
-
-          case CLOCK_PLUGIN_MODE_DIGITAL:
-            plugin->clock_interval = xfce_clock_digital_interval (XFCE_CLOCK_DIGITAL (plugin->clock));
-            break;
-
-          case CLOCK_PLUGIN_MODE_FUZZY:
-            plugin->clock_interval = xfce_clock_fuzzy_interval (XFCE_CLOCK_FUZZY (plugin->clock));
-            break;
-
-          case CLOCK_PLUGIN_MODE_LCD:
-            plugin->clock_interval = xfce_clock_lcd_interval (XFCE_CLOCK_LCD (plugin->clock));
-            break;
-        }
-
-      if (plugin->clock_interval > 0)
-        {
-          /* get ths sync interval */
-          interval = clock_plugin_ms_to_next_interval (plugin->clock_interval);
-
-          /* start the sync timeout */
-          plugin->clock_timeout_id = g_timeout_add (interval, clock_plugin_sync_timeout, plugin);
-        }
-
-      /* update the clock once */
-      (plugin->clock_func) (plugin->clock);
-    }
+  return (timeout->function) (timeout->data);
 }
 
 
 
-static guint
-clock_plugin_ms_to_next_interval (guint timeout_interval)
+static void
+clock_plugin_timeout_destroyed (gpointer user_data)
 {
-  struct tm tm;
-  GTimeVal  timeval;
-  guint     interval;
+  ClockPluginTimeout *timeout = user_data;
+  timeout->timeout_id = 0;
+}
 
-  /* ms to the next second */
-  g_get_current_time (&timeval);
-  interval = 1000 - (timeval.tv_usec / 1000);
 
-  /* leave when we use a per second interval */
-  if (timeout_interval == CLOCK_INTERVAL_SECOND)
-    return interval;
 
-  /* get the current time */
-  clock_plugin_get_localtime (&tm);
+static gboolean
+clock_plugin_timeout_sync (gpointer user_data)
+{
+  ClockPluginTimeout *timeout = user_data;
 
-  /* add the interval time to the next update */
-  switch (timeout_interval)
+  /* run the user function */
+  if ((timeout->function) (timeout->data))
     {
-      /* ms to next hour */
-      case CLOCK_INTERVAL_HOUR:
-        interval += (60 - tm.tm_min) * CLOCK_INTERVAL_MINUTE;
-
-        /* fall-through to add the minutes */
-
-      /* ms to next minute */
-      case CLOCK_INTERVAL_MINUTE:
-        interval += (60 - tm.tm_sec) * CLOCK_INTERVAL_SECOND;
-        break;
+      /* start the real timeout */
+      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, timeout->interval,
+                                                        clock_plugin_timeout_running, timeout,
+                                                        clock_plugin_timeout_destroyed);
+    }
+  else
+    {
+      timeout->timeout_id = 0;
     }
 
-  return interval;
+  /* stop the sync timeout */
+  return FALSE;
 }
 
 
-
-static gboolean
-clock_plugin_tooltip_timeout (gpointer user_data)
+ClockPluginTimeout *
+clock_plugin_timeout_new (guint       interval,
+                          GSourceFunc function,
+                          gpointer    data)
 {
-  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (user_data);
-  gchar       *string;
-  struct tm    tm;
-
-  /* get the local time */
-  clock_plugin_get_localtime (&tm);
-
-  /* get the string */
-  string = clock_plugin_strdup_strftime (plugin->tooltip_format, &tm);
+  ClockPluginTimeout *timeout;
 
-  /* set the tooltip */
-  gtk_widget_set_tooltip_text (GTK_WIDGET (plugin), string);
+  panel_return_val_if_fail (interval > 0, NULL);
+  panel_return_val_if_fail (function != NULL, NULL);
 
-  /* make sure the tooltip is up2date */
-  gtk_widget_trigger_tooltip_query (GTK_WIDGET (plugin));
+  timeout = g_slice_new0 (ClockPluginTimeout);
+  timeout->interval = 0;
+  timeout->function = function;
+  timeout->data = data;
+  timeout->timeout_id = 0;
 
-  /* cleanup */
-  g_free (string);
+  clock_plugin_timeout_set_interval (timeout, interval);
 
-  /* keep the timeout running */
-  return TRUE;
+  return timeout;
 }
 
 
 
-static gboolean
-clock_plugin_tooltip_sync_timeout (gpointer user_data)
+void
+clock_plugin_timeout_set_interval (ClockPluginTimeout *timeout,
+                                   guint               interval)
 {
-  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (user_data);
+  GTimeVal timeval;
+  guint    next_interval;
 
-  /* start the real timeout interval, since we're synced now */
-  plugin->tooltip_timeout_id = g_timeout_add (plugin->tooltip_interval, clock_plugin_tooltip_timeout, plugin);
-
-  /* manual update for this timeout (if really needed) */
-  if (plugin->tooltip_interval > CLOCK_INTERVAL_SECOND)
-    clock_plugin_tooltip_timeout (clock);
-
-  /* stop the sync timeout */
-  return FALSE;
-}
+  panel_return_if_fail (timeout != NULL);
+  panel_return_if_fail (interval > 0);
 
+  /* leave if nothing changed */
+  if (G_UNLIKELY (timeout->interval == interval))
+    return;
+  timeout->interval = interval;
 
+  /* stop running timeout */
+  if (G_LIKELY (timeout->timeout_id != 0))
+    g_source_remove (timeout->timeout_id);
+  timeout->timeout_id = 0;
 
-static void
-clock_plugin_tooltip_sync (ClockPlugin *plugin)
-{
-  guint interval;
+  /* run timeout, leave if it returns false */
+  if (!(timeout->function) (timeout->data))
+    return;
 
-  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
+  /* get the seconds to the next internal (+ 1 second)*/
+  g_get_current_time (&timeval);
+  if (interval == CLOCK_INTERVAL_HOUR)
+    next_interval = 3600 - timeval.tv_sec % 3600;
+  else if (interval == CLOCK_INTERVAL_MINUTE)
+    next_interval = 60 - timeval.tv_sec % 60;
+  else
+    next_interval = 0;
 
-  /* stop a running timeout */
-  if (plugin->tooltip_timeout_id != 0)
+  if (next_interval > 0)
     {
-      g_source_remove (plugin->tooltip_timeout_id);
-      plugin->tooltip_timeout_id = 0;
+      /* start the sync timeout */
+      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, next_interval,
+                                                        clock_plugin_timeout_sync,
+                                                        timeout, NULL);
     }
+  else
+    {
+      /* directly start running the normal timeout */
+      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, interval,
+                                                        clock_plugin_timeout_running, timeout,
+                                                        clock_plugin_timeout_destroyed);
+    }
+}
 
-  /* get the timeout from the string */
-  plugin->tooltip_interval = clock_plugin_interval_from_format (plugin->tooltip_format);
 
-  /* only start the timeout if needed */
-  if (plugin->tooltip_interval > 0)
-    {
-      /* get the interval to sync with the next interval */
-      interval = clock_plugin_ms_to_next_interval (plugin->tooltip_interval);
 
-      /* start the sync timeout */
-      plugin->tooltip_timeout_id = g_timeout_add (interval, clock_plugin_tooltip_sync_timeout, plugin);
-    }
+void
+clock_plugin_timeout_free (ClockPluginTimeout *timeout)
+{
+  panel_return_if_fail (timeout != NULL);
 
-  /* update the tooltip */
-  clock_plugin_tooltip_timeout (plugin);
+  if (G_LIKELY (timeout->timeout_id != 0))
+    g_source_remove (timeout->timeout_id);
+  g_slice_free (ClockPluginTimeout, timeout);
 }
 
 
@@ -791,7 +727,7 @@ clock_plugin_tooltip_sync (ClockPlugin *plugin)
 void
 clock_plugin_get_localtime (struct tm *tm)
 {
-  time_t now = time (0);
+  time_t now = time (NULL);
 
 #ifndef HAVE_LOCALTIME_R
   struct tm *tmbuf;
@@ -801,10 +737,6 @@ clock_plugin_get_localtime (struct tm *tm)
 #else
   localtime_r (&now, tm);
 #endif
-
-#ifdef USE_DEBUG_TIME
-  xfce_clock_util_get_debug_localtime (tm);
-#endif
 }
 
 
@@ -876,4 +808,3 @@ clock_plugin_interval_from_format (const gchar *format)
 
   return interval;
 }
-
diff --git a/plugins/clock/clock.h b/plugins/clock/clock.h
index cd46e0a..077fccf 100644
--- a/plugins/clock/clock.h
+++ b/plugins/clock/clock.h
@@ -26,19 +26,13 @@
 
 G_BEGIN_DECLS
 
-#define CLOCK_INTERVAL_SECOND (1000)
-#define CLOCK_INTERVAL_MINUTE (60 * 1000)
-#define CLOCK_INTERVAL_HOUR   (3600 * 1000)
+#define CLOCK_INTERVAL_SECOND (1)
+#define CLOCK_INTERVAL_MINUTE (60)
+#define CLOCK_INTERVAL_HOUR   (3600)
 
-#define BUFFER_SIZE            256
-#define DEFAULT_TOOLTIP_FORMAT "%A %d %B %Y"
-#define DEFAULT_DIGITAL_FORMAT "%R"
-
-
-
-typedef struct _ClockPlugin      ClockPlugin;
-typedef struct _ClockPluginClass ClockPluginClass;
-typedef enum   _ClockPluginMode  ClockPluginMode;
+typedef struct _ClockPlugin        ClockPlugin;
+typedef struct _ClockPluginClass   ClockPluginClass;
+typedef struct _ClockPluginTimeout ClockPluginTimeout;
 
 #define XFCE_TYPE_CLOCK_PLUGIN            (clock_plugin_get_type ())
 #define XFCE_CLOCK_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_CLOCK_PLUGIN, ClockPlugin))
@@ -49,16 +43,25 @@ typedef enum   _ClockPluginMode  ClockPluginMode;
 
 
 
-GType      clock_plugin_get_type             (void) G_GNUC_CONST;
+GType               clock_plugin_get_type             (void) G_GNUC_CONST;
+
+void                clock_plugin_register_type        (GTypeModule        *type_module);
+
+ClockPluginTimeout *clock_plugin_timeout_new          (guint               interval,
+                                                       GSourceFunc         function,
+                                                       gpointer            data);
+
+void                clock_plugin_timeout_set_interval (ClockPluginTimeout *timeout,
+                                                       guint               interval);
 
-void       clock_plugin_register_type        (GTypeModule     *type_module);
+void                clock_plugin_timeout_free         (ClockPluginTimeout *timeout);
 
-void       clock_plugin_get_localtime        (struct tm       *tm);
+void                clock_plugin_get_localtime        (struct tm          *tm);
 
-gchar     *clock_plugin_strdup_strftime      (const gchar     *format,
-                                              const struct tm *tm);
+gchar              *clock_plugin_strdup_strftime      (const gchar        *format,
+                                                       const struct tm    *tm);
 
-guint      clock_plugin_interval_from_format (const gchar     *format);
+guint               clock_plugin_interval_from_format (const gchar        *format);
 
 G_END_DECLS
 



More information about the Xfce4-commits mailing list