Javier Jardón has proposed merging lp:~jjardon/indicator-datetime/timer-fix-837440 into lp:indicator-datetime.
Requested reviews: Indicator Applet Developers (indicator-applet-developers) Related bugs: Bug #837440 in Indicator Date and Time: "Use GnomeWallClock api to implement wall clocks" https://bugs.launchpad.net/indicator-datetime/+bug/837440 For more details, see: https://code.launchpad.net/~jjardon/indicator-datetime/timer-fix-837440/+merge/77625 -- https://code.launchpad.net/~jjardon/indicator-datetime/timer-fix-837440/+merge/77625 Your team ayatana-commits is subscribed to branch lp:indicator-datetime.
=== modified file 'configure.ac' --- configure.ac 2011-09-29 20:27:52 +0000 +++ configure.ac 2011-09-30 00:00:28 +0000 @@ -60,6 +60,7 @@ DBUSMENUGLIB_REQUIRED_VERSION=0.1.1 DBUSMENUGTK_REQUIRED_VERSION=0.3.94 GIO_REQUIRED_VERSION=2.25.11 +GSETTINGS_DESKTOP_SCHEMAS_REQUIRED=3.1.4 INDICATOR_DISPLAY_OBJECTS=0.2.2 GEOCLUE_REQUIRED_VERSION=0.12.0 ECAL_REQUIRED_VERSION=2.30 @@ -74,6 +75,7 @@ AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(INDICATOR, indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION glib-2.0 >= $GLIB_REQUIRED_VERSION + gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS) @@ -89,6 +91,7 @@ ) PKG_CHECK_MODULES(SERVICE, indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION + gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED glib-2.0 >= $GLIB_REQUIRED_VERSION dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION @@ -114,6 +117,30 @@ gtk+-3.0 >= $GTK3_REQUIRED_VERSION) ########################### +# Check for timerfd support +########################### +AC_CACHE_CHECK([for timerfd_create(2) system call], + [gnome_cv_timerfd], + [AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#include <sys/timerfd.h> +#include <unistd.h> +]],[[ +int +main (void) +{ + timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC); + return 0; +} +]])], + [gnome_cv_timerfd=yes], + [gnome_cv_timerfd=no]])) +if test x"$gnome_cv_timerfd" = x"yes"; then + AC_DEFINE([HAVE_TIMERFD], [1], + [we have the timerfd_create(2) system call]) +fi + +########################### # Grab the GSettings Macros ########################### === modified file 'src/Makefile.am' --- src/Makefile.am 2011-09-06 14:25:34 +0000 +++ src/Makefile.am 2011-09-30 00:00:28 +0000 @@ -8,6 +8,10 @@ datetime-interface.c \ datetime-interface.h \ gen-datetime-service.xml.c \ + gnome-datetime-source.c \ + gnome-datetime-source.h \ + gnome-wall-clock.c \ + gnome-wall-clock.h \ datetime-service.c \ utils.c \ utils.h \ @@ -27,6 +31,10 @@ libdatetime_la_SOURCES = \ gen-datetime-service.xml.h \ dbus-shared.h \ + gnome-datetime-source.c \ + gnome-datetime-source.h \ + gnome-wall-clock.c \ + gnome-wall-clock.h \ settings-shared.h \ utils.c \ utils.h \ === modified file 'src/datetime-service.c' --- src/datetime-service.c 2011-09-29 19:57:50 +0000 +++ src/datetime-service.c 2011-09-30 00:00:28 +0000 @@ -51,6 +51,7 @@ #include "datetime-interface.h" #include "dbus-shared.h" +#include "gnome-wall-clock.h" #include "settings-shared.h" #include "utils.h" @@ -58,7 +59,6 @@ static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data); static gboolean update_appointment_menu_items (gpointer user_data); static gboolean update_timezone_menu_items(gpointer user_data); -static void setup_timer (void); static void geo_client_invalid (GeoclueMasterClient * client, gpointer user_data); static void geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar * c, gchar * d, gpointer user_data); static gboolean get_greeter_mode (void); @@ -1161,7 +1161,6 @@ update_current_timezone(); datetime_interface_update(DATETIME_INTERFACE(user_data)); update_datetime(NULL); - setup_timer(); return; } @@ -1171,6 +1170,8 @@ { GFile * timezonefile = g_file_new_for_path(TIMEZONE_FILE); GFileMonitor * monitor = g_file_monitor_file(timezonefile, G_FILE_MONITOR_NONE, NULL, NULL); + g_object_unref (timezonefile); + if (monitor != NULL) { g_signal_connect(G_OBJECT(monitor), "changed", G_CALLBACK(timezone_changed), dbus); g_debug("Monitoring timezone file: '" TIMEZONE_FILE "'"); @@ -1180,41 +1181,12 @@ return; } -/* Source ID for the timer */ -static guint timer = 0; - -/* Execute at a given time, update and setup a new - timer to go again. */ -static gboolean -timer_func (gpointer user_data) -{ - timer = 0; - /* Reset up each time to reduce error */ - setup_timer(); - update_datetime(NULL); - return FALSE; -} - -/* Sets up the time to launch the timer to update the - date in the datetime entry */ static void -setup_timer (void) +on_clock_changed (GnomeWallClock *clock, + GParamSpec *pspec, + gpointer user_data) { - if (timer != 0) { - g_source_remove(timer); - timer = 0; - } - - time_t t; - t = time(NULL); - struct tm * ltime = localtime(&t); - - timer = g_timeout_add_seconds(((23 - ltime->tm_hour) * 60 * 60) + - ((59 - ltime->tm_min) * 60) + - ((60 - ltime->tm_sec)) + 60 /* one minute past */, - timer_func, NULL); - - return; + update_datetime (NULL); } static void @@ -1228,7 +1200,6 @@ if (!idle) { datetime_interface_update(DATETIME_INTERFACE(user_data)); update_datetime(NULL); - setup_timer(); } } return; @@ -1452,6 +1423,8 @@ int main (int argc, char ** argv) { + GnomeWallClock *clock; + g_type_init(); /* Acknowledging the service init and setting up the interface */ @@ -1491,7 +1464,8 @@ build_timezone(dbus); /* Setup the timer */ - setup_timer(); + clock = g_object_new (GNOME_TYPE_WALL_CLOCK, NULL); + g_signal_connect (clock, "notify::clock", G_CALLBACK (on_clock_changed), NULL); /* And watch for system resumes */ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, === added file 'src/gnome-datetime-source.c' --- src/gnome-datetime-source.c 1970-01-01 00:00:00 +0000 +++ src/gnome-datetime-source.c 2011-09-30 00:00:28 +0000 @@ -0,0 +1,283 @@ +/* -*- mode: C; c-file-style: "linux"; indent-tabs-mode: t -*- + * gdatetime-source.c - copy&paste from https://bugzilla.gnome.org/show_bug.cgi?id=655129 + * + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Author: Colin Walters <walt...@verbum.org> + */ + +#include "config.h" + +#define GNOME_DESKTOP_USE_UNSTABLE_API +#include "gnome-datetime-source.h" + +#ifdef HAVE_TIMERFD +#include <sys/timerfd.h> +#include <unistd.h> +#include <string.h> +#endif + +typedef struct _GDateTimeSource GDateTimeSource; +struct _GDateTimeSource +{ + GSource source; + + gint64 real_expiration; + gint64 wakeup_expiration; + + gboolean cancel_on_set : 1; + gboolean initially_expired : 1; + + GPollFD pollfd; +}; + +static inline void +g_datetime_source_reschedule (GDateTimeSource *datetime_source, + gint64 from_monotonic) +{ + datetime_source->wakeup_expiration = from_monotonic + G_TIME_SPAN_SECOND; +} + +static gboolean +g_datetime_source_is_expired (GDateTimeSource *datetime_source) +{ + gint64 real_now; + + real_now = g_get_real_time (); + + if (datetime_source->initially_expired) + return TRUE; + + if (datetime_source->real_expiration <= real_now) + return TRUE; + + /* We can't really detect without system support when things change; + * so just trigger every second. + */ + if (datetime_source->cancel_on_set) + return TRUE; + + return FALSE; +} + +/* In prepare, we're just checking the monotonic time against + * our projected wakeup. + */ +static gboolean +g_datetime_source_prepare (GSource *source, + gint *timeout) +{ + GDateTimeSource *datetime_source = (GDateTimeSource*)source; + gint64 monotonic_now; + +#ifdef HAVE_TIMERFD + if (datetime_source->pollfd.fd != -1) { + *timeout = -1; + return datetime_source->initially_expired; /* Should be TRUE at most one time, FALSE forever after */ + } +#endif + + monotonic_now = g_source_get_time (source); + + if (monotonic_now < datetime_source->wakeup_expiration) { + /* Round up to ensure that we don't try again too early */ + *timeout = (datetime_source->wakeup_expiration - monotonic_now + 999) / 1000; + return FALSE; + } + + *timeout = 0; + return g_datetime_source_is_expired (datetime_source); +} + +/* In check, we're looking at the wall clock. + */ +static gboolean +g_datetime_source_check (GSource *source) +{ + GDateTimeSource *datetime_source = (GDateTimeSource*)source; + +#ifdef HAVE_TIMERFD + if (datetime_source->pollfd.fd != -1) + return datetime_source->pollfd.revents != 0; +#endif + + if (g_datetime_source_is_expired (datetime_source)) + return TRUE; + + g_datetime_source_reschedule (datetime_source, g_source_get_time (source)); + + return FALSE; +} + +static gboolean +g_datetime_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GDateTimeSource *datetime_source = (GDateTimeSource*)source; + + datetime_source->initially_expired = FALSE; + + if (!callback) { + g_warning ("Timeout source dispatched without callback\n" + "You must call g_source_set_callback()."); + return FALSE; + } + + (callback) (user_data); + + /* Always false as this source is documented to run once */ + return FALSE; +} + +static void +g_datetime_source_finalize (GSource *source) +{ +#ifdef HAVE_TIMERFD + GDateTimeSource *datetime_source = (GDateTimeSource*)source; + if (datetime_source->pollfd.fd != -1) + close (datetime_source->pollfd.fd); +#endif +} + +static GSourceFuncs g_datetime_source_funcs = { + g_datetime_source_prepare, + g_datetime_source_check, + g_datetime_source_dispatch, + g_datetime_source_finalize +}; + +#ifdef HAVE_TIMERFD +static gboolean +g_datetime_source_init_timerfd (GDateTimeSource *datetime_source, + gint64 expected_now_seconds, + gint64 unix_seconds) +{ + struct itimerspec its; + int settime_flags; + + datetime_source->pollfd.fd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC); + if (datetime_source->pollfd.fd == -1) + return FALSE; + + memset (&its, 0, sizeof (its)); + its.it_value.tv_sec = (time_t) unix_seconds; + + /* http://article.gmane.org/gmane.linux.kernel/1132138 */ +#ifndef TFD_TIMER_CANCEL_ON_SET +#define TFD_TIMER_CANCEL_ON_SET (1 << 1) +#endif + + settime_flags = TFD_TIMER_ABSTIME; + if (datetime_source->cancel_on_set) + settime_flags |= TFD_TIMER_CANCEL_ON_SET; + + if (timerfd_settime (datetime_source->pollfd.fd, settime_flags, &its, NULL) < 0) { + close (datetime_source->pollfd.fd); + datetime_source->pollfd.fd = -1; + return FALSE; + } + + /* Now we need to check that the clock didn't go backwards before we + * had the timerfd set up. See + * https://bugzilla.gnome.org/show_bug.cgi?id=655129 + */ + clock_gettime (CLOCK_REALTIME, &its.it_value); + if (its.it_value.tv_sec < expected_now_seconds) + datetime_source->initially_expired = TRUE; + + datetime_source->pollfd.events = G_IO_IN; + + g_source_add_poll ((GSource*) datetime_source, &datetime_source->pollfd); + + return TRUE; +} +#endif + +/** + * _gnome_date_time_source_new: + * @now: The expected current time + * @expiry: Time to await + * @cancel_on_set: Also invoke callback if the system clock changes discontiguously + * + * This function is designed for programs that want to schedule an + * event based on real (wall clock) time, as returned by + * g_get_real_time(). For example, HOUR:MINUTE wall-clock displays + * and calendaring software. The callback will be invoked when the + * specified wall clock time @expiry is reached. This includes + * events such as the system clock being set past the given time. + * + * Compare versus g_timeout_source_new() which is defined to use + * monotonic time as returned by g_get_monotonic_time(). + * + * The parameter @now is necessary to avoid a race condition in + * between getting the current time and calling this function. + * + * If @cancel_on_set is given, the callback will also be invoked at + * most a second after the system clock is changed. This includes + * being set backwards or forwards, and system + * resume from suspend. Not all operating systems allow detecting all + * relevant events efficiently - this function may cause the process + * to wake up once a second in those cases. + * + * A wall clock display should use @cancel_on_set; a calendaring + * program shouldn't need to. + * + * Note that the return value from the associated callback will be + * ignored; this is a one time watch. + * + * <note><para>This function currently does not detect time zone + * changes. On Linux, your program should also monitor the + * <literal>/etc/timezone</literal> file using + * #GFileMonitor.</para></note> + * + * <example id="gdatetime-example-watch"><title>Clock example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../glib/tests/glib-clock.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> + * + * Return value: A newly-constructed #GSource + * + * Since: 2.30 + **/ +GSource * +_gnome_datetime_source_new (GDateTime *now, + GDateTime *expiry, + gboolean cancel_on_set) +{ + GDateTimeSource *datetime_source; + gint64 unix_seconds; + + unix_seconds = g_date_time_to_unix (expiry); + + datetime_source = (GDateTimeSource*) g_source_new (&g_datetime_source_funcs, sizeof (GDateTimeSource)); + + datetime_source->cancel_on_set = cancel_on_set; + +#ifdef HAVE_TIMERFD + { + gint64 expected_now_seconds = g_date_time_to_unix (now); + if (g_datetime_source_init_timerfd (datetime_source, expected_now_seconds, unix_seconds)) + return (GSource*)datetime_source; + /* Fall through to non-timerfd code */ + } +#endif + + datetime_source->real_expiration = unix_seconds * 1000000; + g_datetime_source_reschedule (datetime_source, g_get_monotonic_time ()); + + return (GSource*)datetime_source; +} + === added file 'src/gnome-datetime-source.h' --- src/gnome-datetime-source.h 1970-01-01 00:00:00 +0000 +++ src/gnome-datetime-source.h 2011-09-30 00:00:28 +0000 @@ -0,0 +1,34 @@ +/* gnome-rr.h + * + * Copyright 2011, Red Hat, Inc. + * + * This file is part of the Gnome Library. + * + * The Gnome Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The Gnome Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the Gnome Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Colin Walters <walt...@verbum.org> + */ + +#ifndef GNOME_DATETIME_SOURCE_H +#define GNOME_DATETIME_SOURCE_H + +#include <glib.h> + +GSource *_gnome_datetime_source_new (GDateTime *now, + GDateTime *expiry, + gboolean cancel_on_set); + +#endif /* GNOME_DATETIME_SOURCE_H */ === added file 'src/gnome-wall-clock.c' --- src/gnome-wall-clock.c 1970-01-01 00:00:00 +0000 +++ src/gnome-wall-clock.c 2011-09-30 00:00:28 +0000 @@ -0,0 +1,247 @@ +/* -*- mode: C; c-file-style: "linux"; indent-tabs-mode: t -*- + * gnome-wall-clock.h - monitors TZ setting files and signals changes + * + * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Author: Colin Walters <walt...@verbum.org> + */ + +#include "config.h" + +#include <glib/gi18n-lib.h> + +#include "gnome-wall-clock.h" +#include <gdesktop-enums.h> +#include "gnome-datetime-source.h" + +struct _GnomeWallClockPrivate { + guint clock_update_id; + + char *clock_string; + + GFileMonitor *tz_monitor; + GSettings *desktop_settings; +}; + +enum { + PROP_0, + PROP_CLOCK +}; + +G_DEFINE_TYPE (GnomeWallClock, gnome_wall_clock, G_TYPE_OBJECT); + +static gboolean update_clock (gpointer data); +static void on_schema_change (GSettings *schema, + const char *key, + gpointer user_data); +static void on_tz_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent *event, + gpointer user_data); + + +static void +gnome_wall_clock_init (GnomeWallClock *self) +{ + GFile *tz; + + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_WALL_CLOCK, GnomeWallClockPrivate); + + self->priv->clock_string = NULL; + + tz = g_file_new_for_path ("/etc/localtime"); + self->priv->tz_monitor = g_file_monitor_file (tz, 0, NULL, NULL); + g_object_unref (tz); + + g_signal_connect (self->priv->tz_monitor, "changed", G_CALLBACK (on_tz_changed), self); + + self->priv->desktop_settings = g_settings_new ("org.gnome.desktop.interface"); + g_signal_connect (self->priv->desktop_settings, "changed", G_CALLBACK (on_schema_change), self); + + update_clock (self); +} + +static void +gnome_wall_clock_dispose (GObject *object) +{ + GnomeWallClock *self = GNOME_WALL_CLOCK (object); + + if (self->priv->clock_update_id) { + g_source_remove (self->priv->clock_update_id); + self->priv->clock_update_id = 0; + } + + if (self->priv->tz_monitor != NULL) { + g_object_unref (self->priv->tz_monitor); + self->priv->tz_monitor = NULL; + } + + if (self->priv->desktop_settings != NULL) { + g_object_unref (self->priv->desktop_settings); + self->priv->desktop_settings = NULL; + } + + G_OBJECT_CLASS (gnome_wall_clock_parent_class)->dispose (object); +} + +static void +gnome_wall_clock_finalize (GObject *object) +{ + GnomeWallClock *self = GNOME_WALL_CLOCK (object); + + g_free (self->priv->clock_string); + + G_OBJECT_CLASS (gnome_wall_clock_parent_class)->finalize (object); +} + +static void +gnome_wall_clock_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GnomeWallClock *self = GNOME_WALL_CLOCK (gobject); + + switch (prop_id) + { + case PROP_CLOCK: + g_value_set_string (value, self->priv->clock_string); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +gnome_wall_clock_class_init (GnomeWallClockClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = gnome_wall_clock_get_property; + gobject_class->dispose = gnome_wall_clock_dispose; + gobject_class->finalize = gnome_wall_clock_finalize; + + /** + * GnomeWallClock:clock: + * + * A formatted string representing the current clock display. + */ + g_object_class_install_property (gobject_class, + PROP_CLOCK, + g_param_spec_string ("clock", + "", + "", + NULL, + G_PARAM_READABLE)); + + + g_type_class_add_private (gobject_class, sizeof (GnomeWallClockPrivate)); +} + +static gboolean +update_clock (gpointer data) +{ + GnomeWallClock *self = data; + GDesktopClockFormat clock_format; + const char *format_string; + gboolean show_date; + gboolean show_seconds; + GSource *source; + GDateTime *now; + GDateTime *expiry; + + clock_format = g_settings_get_enum (self->priv->desktop_settings, "clock-format"); + show_date = g_settings_get_boolean (self->priv->desktop_settings, "clock-show-date"); + show_seconds = g_settings_get_boolean (self->priv->desktop_settings, "clock-show-seconds"); + + now = g_date_time_new_now_local (); + if (show_seconds) + expiry = g_date_time_add_seconds (now, 1); + else + expiry = g_date_time_add_seconds (now, 60 - g_date_time_get_second (now)); + + if (self->priv->clock_update_id) + g_source_remove (self->priv->clock_update_id); + + source = _gnome_datetime_source_new (now, expiry, TRUE); + g_source_set_priority (source, G_PRIORITY_HIGH); + g_source_set_callback (source, update_clock, self, NULL); + self->priv->clock_update_id = g_source_attach (source, NULL); + g_source_unref (source); + + if (clock_format == G_DESKTOP_CLOCK_FORMAT_24H) { + if (show_date) + /* Translators: This is the time format with date used + in 24-hour mode. */ + format_string = show_seconds ? _("%a %b %e, %R:%S") + : _("%a %b %e, %R"); + else + /* Translators: This is the time format without date used + in 24-hour mode. */ + format_string = show_seconds ? _("%a %R:%S") + : _("%a %R"); + } else { + if (show_date) + /* Translators: This is a time format with date used + for AM/PM. */ + format_string = show_seconds ? _("%a %b %e, %l:%M:%S %p") + : _("%a %b %e, %l:%M %p"); + else + /* Translators: This is a time format without date used + for AM/PM. */ + format_string = show_seconds ? _("%a %l:%M:%S %p") + : _("%a %l:%M %p"); + } + + g_free (self->priv->clock_string); + self->priv->clock_string = g_date_time_format (now, format_string); + + g_date_time_unref (now); + g_date_time_unref (expiry); + + g_object_notify ((GObject*)self, "clock"); + + return FALSE; +} + +static void +on_schema_change (GSettings *schema, + const char *key, + gpointer user_data) +{ + update_clock (user_data); +} + +static void +on_tz_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent *event, + gpointer user_data) +{ + update_clock (user_data); +} + +const char * +gnome_wall_clock_get_clock (GnomeWallClock *clock) +{ + return clock->priv->clock_string; +} === added file 'src/gnome-wall-clock.h' --- src/gnome-wall-clock.h 1970-01-01 00:00:00 +0000 +++ src/gnome-wall-clock.h 2011-09-30 00:00:28 +0000 @@ -0,0 +1,62 @@ +/* gnome-tz-monitor.h - fade window background between two surfaces + + Copyright 2008, Red Hat, Inc. + Copyright 2011, Red Hat, Inc. + + This file is part of the Gnome Library. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Colin Walters <walt...@verbum.org> +*/ + +#ifndef __GNOME_WALL_CLOCK_H__ +#define __GNOME_WALL_CLOCK_H__ + +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define GNOME_TYPE_WALL_CLOCK (gnome_wall_clock_get_type ()) +#define GNOME_WALL_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_WALL_CLOCK, GnomeWallClock)) +#define GNOME_WALL_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_WALL_CLOCK, GnomeWallClockClass)) +#define GNOME_IS_WALL_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_WALL_CLOCK)) +#define GNOME_IS_WALL_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_WALL_CLOCK)) +#define GNOME_WALL_CLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_WALL_CLOCK, GnomeWallClockClass)) + +typedef struct _GnomeWallClockPrivate GnomeWallClockPrivate; +typedef struct _GnomeWallClock GnomeWallClock; +typedef struct _GnomeWallClockClass GnomeWallClockClass; + +struct _GnomeWallClock +{ + GObject parent_object; + + GnomeWallClockPrivate *priv; +}; + +struct _GnomeWallClockClass +{ + GObjectClass parent_class; +}; + +GType gnome_wall_clock_get_type (void); + +const char * gnome_wall_clock_get_clock (GnomeWallClock *clock); + +G_END_DECLS + +#endif === modified file 'src/indicator-datetime.c' --- src/indicator-datetime.c 2011-09-21 20:19:53 +0000 +++ src/indicator-datetime.c 2011-09-30 00:00:28 +0000 @@ -48,6 +48,7 @@ #include "utils.h" #include "dbus-shared.h" #include "settings-shared.h" +#include "gnome-wall-clock.h" #define INDICATOR_DATETIME_TYPE (indicator_datetime_get_type ()) @@ -72,7 +73,6 @@ struct _IndicatorDatetimePrivate { GtkLabel * label; - guint timer; gchar * time_string; @@ -101,8 +101,11 @@ GList * timezone_items; GSettings * settings; + GSettings * gnome_settings; GtkSizeGroup * indicator_right_group; + + GnomeWallClock *clock; }; /* Enum for the properties so that they can be quickly @@ -166,7 +169,7 @@ static gchar * generate_format_string_now (IndicatorDatetime * self); static void update_label (IndicatorDatetime * io, GDateTime ** datetime); static void guess_label_size (IndicatorDatetime * self); -static void setup_timer (IndicatorDatetime * self, GDateTime * datetime); +static void on_clock_changed (GnomeWallClock *clock, GParamSpec *pspec, gpointer user_data); static void update_time (IndicatorDatetime * self); static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data); static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data); @@ -293,7 +296,6 @@ IndicatorDatetimePrivate); self->priv->label = NULL; - self->priv->timer = 0; self->priv->idle_measure = 0; self->priv->max_width = 0; @@ -362,6 +364,11 @@ g_warning("Unable to get settings for '" SETTINGS_INTERFACE "'"); } + self->priv->gnome_settings = g_settings_new ("org.gnome.desktop.interface"); + + self->priv->clock = g_object_new (GNOME_TYPE_WALL_CLOCK, NULL); + g_signal_connect (self->priv->clock, "notify::clock", G_CALLBACK (on_clock_changed), self); + self->priv->sm = indicator_service_manager_new_version(SERVICE_NAME, SERVICE_VERSION); self->priv->indicator_right_group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); @@ -433,9 +440,9 @@ self->priv->label = NULL; } - if (self->priv->timer != 0) { - g_source_remove(self->priv->timer); - self->priv->timer = 0; + if (self->priv->clock != NULL) { + g_object_unref (self->priv->clock); + self->priv->clock = NULL; } if (self->priv->idle_measure != 0) { @@ -562,7 +569,7 @@ if (newval != self->priv->time_mode) { update = TRUE; self->priv->time_mode = newval; - setup_timer(self, NULL); + update_time (self); } break; } @@ -571,8 +578,11 @@ self->priv->show_seconds = !self->priv->show_seconds; if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) { update = TRUE; - setup_timer(self, NULL); + update_time (self); } + g_settings_set_boolean (self->priv->gnome_settings, + "clock-show-seconds", + self->priv->show_seconds); } break; } @@ -606,8 +616,11 @@ self->priv->custom_show_seconds = (time_mask & STRFTIME_MASK_SECONDS); if (self->priv->time_mode == SETTINGS_TIME_CUSTOM) { update = TRUE; - setup_timer(self, NULL); + update_time (self); } + g_settings_set_boolean (self->priv->gnome_settings, + "clock-show-seconds", + self->priv->show_seconds); } break; } @@ -831,12 +844,21 @@ update_label(self, &dt); timezone_update_all_labels(self); if (dt != NULL) { - setup_timer(self, dt); g_date_time_unref(dt); } return; } +static void +on_clock_changed (GnomeWallClock *clock, + GParamSpec *pspec, + gpointer user_data) +{ + IndicatorDatetime *self = INDICATOR_DATETIME (user_data); + + update_time (self); +} + /* Receives all signals from the service, routed to the appropriate functions */ static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, @@ -851,54 +873,6 @@ return; } -/* Runs every minute and updates the time */ -gboolean -timer_func (gpointer user_data) -{ - IndicatorDatetime * self = INDICATOR_DATETIME(user_data); - self->priv->timer = 0; - GDateTime * dt = NULL; - update_label(self, &dt); - timezone_update_all_labels(self); - if (dt != NULL) { - setup_timer(self, dt); - g_date_time_unref(dt); - } - return FALSE; -} - -/* Configure the timer to run the next time through */ -static void -setup_timer (IndicatorDatetime * self, GDateTime * datetime) -{ - gboolean unref = FALSE; - - if (self->priv->timer != 0) { - g_source_remove(self->priv->timer); - self->priv->timer = 0; - } - - if (self->priv->show_seconds || - (self->priv->time_mode == SETTINGS_TIME_CUSTOM && self->priv->custom_show_seconds)) { - self->priv->timer = g_timeout_add_full(G_PRIORITY_HIGH, 999, timer_func, self, NULL); - } else { - if (datetime == NULL) { - datetime = g_date_time_new_now_local(); - unref = TRUE; - } - - /* Plus 2 so we're just after the minute, don't want to be early. */ - gint seconds = (gint)g_date_time_get_seconds(datetime); - self->priv->timer = g_timeout_add_seconds(60 - seconds + 2, timer_func, self); - - if (unref) { - g_date_time_unref(datetime); - } - } - - return; -} - /* Does a quick meausre of how big the string is in pixels with a Pango layout */ static gint @@ -1521,10 +1495,6 @@ gtk_widget_set_visible(GTK_WIDGET (self->priv->label), self->priv->show_clock); } - if (self->priv->timer == 0) { - setup_timer(self, NULL); - } - return self->priv->label; }
_______________________________________________ Mailing list: https://launchpad.net/~ayatana-commits Post to : ayatana-commits@lists.launchpad.net Unsubscribe : https://launchpad.net/~ayatana-commits More help : https://help.launchpad.net/ListHelp