Merge lp:~jjardon/indicator-datetime/timer-fix-837440 into lp:indicator-datetime/0.3

Proposed by Javier Jardón on 2011-09-29
Status: Rejected
Rejected by: Ted Gould on 2011-09-30
Proposed branch: lp:~jjardon/indicator-datetime/timer-fix-837440
Merge into: lp:indicator-datetime/0.3
Diff against target: 1037 lines (+704/-99)
8 files modified
configure.ac (+27/-0)
src/Makefile.am (+8/-0)
src/datetime-service.c (+11/-37)
src/gnome-datetime-source.c (+283/-0)
src/gnome-datetime-source.h (+34/-0)
src/gnome-wall-clock.c (+247/-0)
src/gnome-wall-clock.h (+62/-0)
src/indicator-datetime.c (+32/-62)
To merge this branch: bzr merge lp:~jjardon/indicator-datetime/timer-fix-837440
Reviewer Review Type Date Requested Status
Ted Gould (community) 2011-09-29 Disapprove on 2011-09-30
Review via email: mp+77625@code.launchpad.net
To post a comment you must log in.
Ted Gould (ted) wrote :

Indicator-datetime needs to have all contributions be copyright Canonical. I'm guessing those contributors won't sign the CLA :-)

review: Disapprove

Unmerged revisions

141. By Javier Jardón on 2011-09-29

configure.ac: Chack for timerfd support

140. By Javier Jardón on 2011-09-29

indicator-datetime: Use GnomeWallClock instead manual timers

139. By Javier Jardón on 2011-09-29

datetime-service: Use GnomeWallClock instead manual timers

138. By Javier Jardón on 2011-09-29

Copy GnomeWallClock to our tree

So we do not have to depend on unstable API

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2011-09-29 20:27:52 +0000
3+++ configure.ac 2011-09-30 00:00:28 +0000
4@@ -60,6 +60,7 @@
5 DBUSMENUGLIB_REQUIRED_VERSION=0.1.1
6 DBUSMENUGTK_REQUIRED_VERSION=0.3.94
7 GIO_REQUIRED_VERSION=2.25.11
8+GSETTINGS_DESKTOP_SCHEMAS_REQUIRED=3.1.4
9 INDICATOR_DISPLAY_OBJECTS=0.2.2
10 GEOCLUE_REQUIRED_VERSION=0.12.0
11 ECAL_REQUIRED_VERSION=2.30
12@@ -74,6 +75,7 @@
13 AS_IF([test "x$with_gtk" = x3],
14 [PKG_CHECK_MODULES(INDICATOR, indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION
15 glib-2.0 >= $GLIB_REQUIRED_VERSION
16+ gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED
17 dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION
18 dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION
19 libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS)
20@@ -89,6 +91,7 @@
21 )
22
23 PKG_CHECK_MODULES(SERVICE, indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION
24+ gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED
25 glib-2.0 >= $GLIB_REQUIRED_VERSION
26 dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION
27 dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION
28@@ -114,6 +117,30 @@
29 gtk+-3.0 >= $GTK3_REQUIRED_VERSION)
30
31 ###########################
32+# Check for timerfd support
33+###########################
34+AC_CACHE_CHECK([for timerfd_create(2) system call],
35+ [gnome_cv_timerfd],
36+ [AC_COMPILE_IFELSE([
37+ AC_LANG_PROGRAM([[
38+#include <sys/timerfd.h>
39+#include <unistd.h>
40+]],[[
41+int
42+main (void)
43+{
44+ timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC);
45+ return 0;
46+}
47+]])],
48+ [gnome_cv_timerfd=yes],
49+ [gnome_cv_timerfd=no]]))
50+if test x"$gnome_cv_timerfd" = x"yes"; then
51+ AC_DEFINE([HAVE_TIMERFD], [1],
52+ [we have the timerfd_create(2) system call])
53+fi
54+
55+###########################
56 # Grab the GSettings Macros
57 ###########################
58
59
60=== modified file 'src/Makefile.am'
61--- src/Makefile.am 2011-09-06 14:25:34 +0000
62+++ src/Makefile.am 2011-09-30 00:00:28 +0000
63@@ -8,6 +8,10 @@
64 datetime-interface.c \
65 datetime-interface.h \
66 gen-datetime-service.xml.c \
67+ gnome-datetime-source.c \
68+ gnome-datetime-source.h \
69+ gnome-wall-clock.c \
70+ gnome-wall-clock.h \
71 datetime-service.c \
72 utils.c \
73 utils.h \
74@@ -27,6 +31,10 @@
75 libdatetime_la_SOURCES = \
76 gen-datetime-service.xml.h \
77 dbus-shared.h \
78+ gnome-datetime-source.c \
79+ gnome-datetime-source.h \
80+ gnome-wall-clock.c \
81+ gnome-wall-clock.h \
82 settings-shared.h \
83 utils.c \
84 utils.h \
85
86=== modified file 'src/datetime-service.c'
87--- src/datetime-service.c 2011-09-29 19:57:50 +0000
88+++ src/datetime-service.c 2011-09-30 00:00:28 +0000
89@@ -51,6 +51,7 @@
90
91 #include "datetime-interface.h"
92 #include "dbus-shared.h"
93+#include "gnome-wall-clock.h"
94 #include "settings-shared.h"
95 #include "utils.h"
96
97@@ -58,7 +59,6 @@
98 static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data);
99 static gboolean update_appointment_menu_items (gpointer user_data);
100 static gboolean update_timezone_menu_items(gpointer user_data);
101-static void setup_timer (void);
102 static void geo_client_invalid (GeoclueMasterClient * client, gpointer user_data);
103 static void geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar * c, gchar * d, gpointer user_data);
104 static gboolean get_greeter_mode (void);
105@@ -1161,7 +1161,6 @@
106 update_current_timezone();
107 datetime_interface_update(DATETIME_INTERFACE(user_data));
108 update_datetime(NULL);
109- setup_timer();
110 return;
111 }
112
113@@ -1171,6 +1170,8 @@
114 {
115 GFile * timezonefile = g_file_new_for_path(TIMEZONE_FILE);
116 GFileMonitor * monitor = g_file_monitor_file(timezonefile, G_FILE_MONITOR_NONE, NULL, NULL);
117+ g_object_unref (timezonefile);
118+
119 if (monitor != NULL) {
120 g_signal_connect(G_OBJECT(monitor), "changed", G_CALLBACK(timezone_changed), dbus);
121 g_debug("Monitoring timezone file: '" TIMEZONE_FILE "'");
122@@ -1180,41 +1181,12 @@
123 return;
124 }
125
126-/* Source ID for the timer */
127-static guint timer = 0;
128-
129-/* Execute at a given time, update and setup a new
130- timer to go again. */
131-static gboolean
132-timer_func (gpointer user_data)
133-{
134- timer = 0;
135- /* Reset up each time to reduce error */
136- setup_timer();
137- update_datetime(NULL);
138- return FALSE;
139-}
140-
141-/* Sets up the time to launch the timer to update the
142- date in the datetime entry */
143 static void
144-setup_timer (void)
145+on_clock_changed (GnomeWallClock *clock,
146+ GParamSpec *pspec,
147+ gpointer user_data)
148 {
149- if (timer != 0) {
150- g_source_remove(timer);
151- timer = 0;
152- }
153-
154- time_t t;
155- t = time(NULL);
156- struct tm * ltime = localtime(&t);
157-
158- timer = g_timeout_add_seconds(((23 - ltime->tm_hour) * 60 * 60) +
159- ((59 - ltime->tm_min) * 60) +
160- ((60 - ltime->tm_sec)) + 60 /* one minute past */,
161- timer_func, NULL);
162-
163- return;
164+ update_datetime (NULL);
165 }
166
167 static void
168@@ -1228,7 +1200,6 @@
169 if (!idle) {
170 datetime_interface_update(DATETIME_INTERFACE(user_data));
171 update_datetime(NULL);
172- setup_timer();
173 }
174 }
175 return;
176@@ -1452,6 +1423,8 @@
177 int
178 main (int argc, char ** argv)
179 {
180+ GnomeWallClock *clock;
181+
182 g_type_init();
183
184 /* Acknowledging the service init and setting up the interface */
185@@ -1491,7 +1464,8 @@
186 build_timezone(dbus);
187
188 /* Setup the timer */
189- setup_timer();
190+ clock = g_object_new (GNOME_TYPE_WALL_CLOCK, NULL);
191+ g_signal_connect (clock, "notify::clock", G_CALLBACK (on_clock_changed), NULL);
192
193 /* And watch for system resumes */
194 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
195
196=== added file 'src/gnome-datetime-source.c'
197--- src/gnome-datetime-source.c 1970-01-01 00:00:00 +0000
198+++ src/gnome-datetime-source.c 2011-09-30 00:00:28 +0000
199@@ -0,0 +1,283 @@
200+/* -*- mode: C; c-file-style: "linux"; indent-tabs-mode: t -*-
201+ * gdatetime-source.c - copy&paste from https://bugzilla.gnome.org/show_bug.cgi?id=655129
202+ *
203+ * Copyright (C) 2011 Red Hat, Inc.
204+ *
205+ * This program is free software; you can redistribute it and/or
206+ * modify it under the terms of the GNU Library General Public License
207+ * as published by the Free Software Foundation; either version 2 of
208+ * the License, or (at your option) any later version.
209+ *
210+ * This program is distributed in the hope that it will be useful, but
211+ * WITHOUT ANY WARRANTY; without even the implied warranty of
212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
213+ * Library General Public License for more details.
214+ *
215+ * You should have received a copy of the GNU Library General Public
216+ * License along with this program; if not, write to the Free Software
217+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
218+ * 02111-1307, USA.
219+ *
220+ * Author: Colin Walters <walters@verbum.org>
221+ */
222+
223+#include "config.h"
224+
225+#define GNOME_DESKTOP_USE_UNSTABLE_API
226+#include "gnome-datetime-source.h"
227+
228+#ifdef HAVE_TIMERFD
229+#include <sys/timerfd.h>
230+#include <unistd.h>
231+#include <string.h>
232+#endif
233+
234+typedef struct _GDateTimeSource GDateTimeSource;
235+struct _GDateTimeSource
236+{
237+ GSource source;
238+
239+ gint64 real_expiration;
240+ gint64 wakeup_expiration;
241+
242+ gboolean cancel_on_set : 1;
243+ gboolean initially_expired : 1;
244+
245+ GPollFD pollfd;
246+};
247+
248+static inline void
249+g_datetime_source_reschedule (GDateTimeSource *datetime_source,
250+ gint64 from_monotonic)
251+{
252+ datetime_source->wakeup_expiration = from_monotonic + G_TIME_SPAN_SECOND;
253+}
254+
255+static gboolean
256+g_datetime_source_is_expired (GDateTimeSource *datetime_source)
257+{
258+ gint64 real_now;
259+
260+ real_now = g_get_real_time ();
261+
262+ if (datetime_source->initially_expired)
263+ return TRUE;
264+
265+ if (datetime_source->real_expiration <= real_now)
266+ return TRUE;
267+
268+ /* We can't really detect without system support when things change;
269+ * so just trigger every second.
270+ */
271+ if (datetime_source->cancel_on_set)
272+ return TRUE;
273+
274+ return FALSE;
275+}
276+
277+/* In prepare, we're just checking the monotonic time against
278+ * our projected wakeup.
279+ */
280+static gboolean
281+g_datetime_source_prepare (GSource *source,
282+ gint *timeout)
283+{
284+ GDateTimeSource *datetime_source = (GDateTimeSource*)source;
285+ gint64 monotonic_now;
286+
287+#ifdef HAVE_TIMERFD
288+ if (datetime_source->pollfd.fd != -1) {
289+ *timeout = -1;
290+ return datetime_source->initially_expired; /* Should be TRUE at most one time, FALSE forever after */
291+ }
292+#endif
293+
294+ monotonic_now = g_source_get_time (source);
295+
296+ if (monotonic_now < datetime_source->wakeup_expiration) {
297+ /* Round up to ensure that we don't try again too early */
298+ *timeout = (datetime_source->wakeup_expiration - monotonic_now + 999) / 1000;
299+ return FALSE;
300+ }
301+
302+ *timeout = 0;
303+ return g_datetime_source_is_expired (datetime_source);
304+}
305+
306+/* In check, we're looking at the wall clock.
307+ */
308+static gboolean
309+g_datetime_source_check (GSource *source)
310+{
311+ GDateTimeSource *datetime_source = (GDateTimeSource*)source;
312+
313+#ifdef HAVE_TIMERFD
314+ if (datetime_source->pollfd.fd != -1)
315+ return datetime_source->pollfd.revents != 0;
316+#endif
317+
318+ if (g_datetime_source_is_expired (datetime_source))
319+ return TRUE;
320+
321+ g_datetime_source_reschedule (datetime_source, g_source_get_time (source));
322+
323+ return FALSE;
324+}
325+
326+static gboolean
327+g_datetime_source_dispatch (GSource *source,
328+ GSourceFunc callback,
329+ gpointer user_data)
330+{
331+ GDateTimeSource *datetime_source = (GDateTimeSource*)source;
332+
333+ datetime_source->initially_expired = FALSE;
334+
335+ if (!callback) {
336+ g_warning ("Timeout source dispatched without callback\n"
337+ "You must call g_source_set_callback().");
338+ return FALSE;
339+ }
340+
341+ (callback) (user_data);
342+
343+ /* Always false as this source is documented to run once */
344+ return FALSE;
345+}
346+
347+static void
348+g_datetime_source_finalize (GSource *source)
349+{
350+#ifdef HAVE_TIMERFD
351+ GDateTimeSource *datetime_source = (GDateTimeSource*)source;
352+ if (datetime_source->pollfd.fd != -1)
353+ close (datetime_source->pollfd.fd);
354+#endif
355+}
356+
357+static GSourceFuncs g_datetime_source_funcs = {
358+ g_datetime_source_prepare,
359+ g_datetime_source_check,
360+ g_datetime_source_dispatch,
361+ g_datetime_source_finalize
362+};
363+
364+#ifdef HAVE_TIMERFD
365+static gboolean
366+g_datetime_source_init_timerfd (GDateTimeSource *datetime_source,
367+ gint64 expected_now_seconds,
368+ gint64 unix_seconds)
369+{
370+ struct itimerspec its;
371+ int settime_flags;
372+
373+ datetime_source->pollfd.fd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC);
374+ if (datetime_source->pollfd.fd == -1)
375+ return FALSE;
376+
377+ memset (&its, 0, sizeof (its));
378+ its.it_value.tv_sec = (time_t) unix_seconds;
379+
380+ /* http://article.gmane.org/gmane.linux.kernel/1132138 */
381+#ifndef TFD_TIMER_CANCEL_ON_SET
382+#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
383+#endif
384+
385+ settime_flags = TFD_TIMER_ABSTIME;
386+ if (datetime_source->cancel_on_set)
387+ settime_flags |= TFD_TIMER_CANCEL_ON_SET;
388+
389+ if (timerfd_settime (datetime_source->pollfd.fd, settime_flags, &its, NULL) < 0) {
390+ close (datetime_source->pollfd.fd);
391+ datetime_source->pollfd.fd = -1;
392+ return FALSE;
393+ }
394+
395+ /* Now we need to check that the clock didn't go backwards before we
396+ * had the timerfd set up. See
397+ * https://bugzilla.gnome.org/show_bug.cgi?id=655129
398+ */
399+ clock_gettime (CLOCK_REALTIME, &its.it_value);
400+ if (its.it_value.tv_sec < expected_now_seconds)
401+ datetime_source->initially_expired = TRUE;
402+
403+ datetime_source->pollfd.events = G_IO_IN;
404+
405+ g_source_add_poll ((GSource*) datetime_source, &datetime_source->pollfd);
406+
407+ return TRUE;
408+}
409+#endif
410+
411+/**
412+ * _gnome_date_time_source_new:
413+ * @now: The expected current time
414+ * @expiry: Time to await
415+ * @cancel_on_set: Also invoke callback if the system clock changes discontiguously
416+ *
417+ * This function is designed for programs that want to schedule an
418+ * event based on real (wall clock) time, as returned by
419+ * g_get_real_time(). For example, HOUR:MINUTE wall-clock displays
420+ * and calendaring software. The callback will be invoked when the
421+ * specified wall clock time @expiry is reached. This includes
422+ * events such as the system clock being set past the given time.
423+ *
424+ * Compare versus g_timeout_source_new() which is defined to use
425+ * monotonic time as returned by g_get_monotonic_time().
426+ *
427+ * The parameter @now is necessary to avoid a race condition in
428+ * between getting the current time and calling this function.
429+ *
430+ * If @cancel_on_set is given, the callback will also be invoked at
431+ * most a second after the system clock is changed. This includes
432+ * being set backwards or forwards, and system
433+ * resume from suspend. Not all operating systems allow detecting all
434+ * relevant events efficiently - this function may cause the process
435+ * to wake up once a second in those cases.
436+ *
437+ * A wall clock display should use @cancel_on_set; a calendaring
438+ * program shouldn't need to.
439+ *
440+ * Note that the return value from the associated callback will be
441+ * ignored; this is a one time watch.
442+ *
443+ * <note><para>This function currently does not detect time zone
444+ * changes. On Linux, your program should also monitor the
445+ * <literal>/etc/timezone</literal> file using
446+ * #GFileMonitor.</para></note>
447+ *
448+ * <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>
449+ *
450+ * Return value: A newly-constructed #GSource
451+ *
452+ * Since: 2.30
453+ **/
454+GSource *
455+_gnome_datetime_source_new (GDateTime *now,
456+ GDateTime *expiry,
457+ gboolean cancel_on_set)
458+{
459+ GDateTimeSource *datetime_source;
460+ gint64 unix_seconds;
461+
462+ unix_seconds = g_date_time_to_unix (expiry);
463+
464+ datetime_source = (GDateTimeSource*) g_source_new (&g_datetime_source_funcs, sizeof (GDateTimeSource));
465+
466+ datetime_source->cancel_on_set = cancel_on_set;
467+
468+#ifdef HAVE_TIMERFD
469+ {
470+ gint64 expected_now_seconds = g_date_time_to_unix (now);
471+ if (g_datetime_source_init_timerfd (datetime_source, expected_now_seconds, unix_seconds))
472+ return (GSource*)datetime_source;
473+ /* Fall through to non-timerfd code */
474+ }
475+#endif
476+
477+ datetime_source->real_expiration = unix_seconds * 1000000;
478+ g_datetime_source_reschedule (datetime_source, g_get_monotonic_time ());
479+
480+ return (GSource*)datetime_source;
481+}
482+
483
484=== added file 'src/gnome-datetime-source.h'
485--- src/gnome-datetime-source.h 1970-01-01 00:00:00 +0000
486+++ src/gnome-datetime-source.h 2011-09-30 00:00:28 +0000
487@@ -0,0 +1,34 @@
488+/* gnome-rr.h
489+ *
490+ * Copyright 2011, Red Hat, Inc.
491+ *
492+ * This file is part of the Gnome Library.
493+ *
494+ * The Gnome Library is free software; you can redistribute it and/or
495+ * modify it under the terms of the GNU Library General Public License as
496+ * published by the Free Software Foundation; either version 2 of the
497+ * License, or (at your option) any later version.
498+ *
499+ * The Gnome Library is distributed in the hope that it will be useful,
500+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
501+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
502+ * Library General Public License for more details.
503+ *
504+ * You should have received a copy of the GNU Library General Public
505+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
506+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
507+ * Boston, MA 02111-1307, USA.
508+ *
509+ * Author: Colin Walters <walters@verbum.org>
510+ */
511+
512+#ifndef GNOME_DATETIME_SOURCE_H
513+#define GNOME_DATETIME_SOURCE_H
514+
515+#include <glib.h>
516+
517+GSource *_gnome_datetime_source_new (GDateTime *now,
518+ GDateTime *expiry,
519+ gboolean cancel_on_set);
520+
521+#endif /* GNOME_DATETIME_SOURCE_H */
522
523=== added file 'src/gnome-wall-clock.c'
524--- src/gnome-wall-clock.c 1970-01-01 00:00:00 +0000
525+++ src/gnome-wall-clock.c 2011-09-30 00:00:28 +0000
526@@ -0,0 +1,247 @@
527+/* -*- mode: C; c-file-style: "linux"; indent-tabs-mode: t -*-
528+ * gnome-wall-clock.h - monitors TZ setting files and signals changes
529+ *
530+ * Copyright (C) 2010 Red Hat, Inc.
531+ * Copyright (C) 2011 Red Hat, Inc.
532+ *
533+ * This program is free software; you can redistribute it and/or
534+ * modify it under the terms of the GNU Library General Public License
535+ * as published by the Free Software Foundation; either version 2 of
536+ * the License, or (at your option) any later version.
537+ *
538+ * This program is distributed in the hope that it will be useful, but
539+ * WITHOUT ANY WARRANTY; without even the implied warranty of
540+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
541+ * Library General Public License for more details.
542+ *
543+ * You should have received a copy of the GNU Library General Public
544+ * License along with this program; if not, write to the Free Software
545+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
546+ * 02111-1307, USA.
547+ *
548+ * Author: Colin Walters <walters@verbum.org>
549+ */
550+
551+#include "config.h"
552+
553+#include <glib/gi18n-lib.h>
554+
555+#include "gnome-wall-clock.h"
556+#include <gdesktop-enums.h>
557+#include "gnome-datetime-source.h"
558+
559+struct _GnomeWallClockPrivate {
560+ guint clock_update_id;
561+
562+ char *clock_string;
563+
564+ GFileMonitor *tz_monitor;
565+ GSettings *desktop_settings;
566+};
567+
568+enum {
569+ PROP_0,
570+ PROP_CLOCK
571+};
572+
573+G_DEFINE_TYPE (GnomeWallClock, gnome_wall_clock, G_TYPE_OBJECT);
574+
575+static gboolean update_clock (gpointer data);
576+static void on_schema_change (GSettings *schema,
577+ const char *key,
578+ gpointer user_data);
579+static void on_tz_changed (GFileMonitor *monitor,
580+ GFile *file,
581+ GFile *other_file,
582+ GFileMonitorEvent *event,
583+ gpointer user_data);
584+
585+
586+static void
587+gnome_wall_clock_init (GnomeWallClock *self)
588+{
589+ GFile *tz;
590+
591+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_WALL_CLOCK, GnomeWallClockPrivate);
592+
593+ self->priv->clock_string = NULL;
594+
595+ tz = g_file_new_for_path ("/etc/localtime");
596+ self->priv->tz_monitor = g_file_monitor_file (tz, 0, NULL, NULL);
597+ g_object_unref (tz);
598+
599+ g_signal_connect (self->priv->tz_monitor, "changed", G_CALLBACK (on_tz_changed), self);
600+
601+ self->priv->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
602+ g_signal_connect (self->priv->desktop_settings, "changed", G_CALLBACK (on_schema_change), self);
603+
604+ update_clock (self);
605+}
606+
607+static void
608+gnome_wall_clock_dispose (GObject *object)
609+{
610+ GnomeWallClock *self = GNOME_WALL_CLOCK (object);
611+
612+ if (self->priv->clock_update_id) {
613+ g_source_remove (self->priv->clock_update_id);
614+ self->priv->clock_update_id = 0;
615+ }
616+
617+ if (self->priv->tz_monitor != NULL) {
618+ g_object_unref (self->priv->tz_monitor);
619+ self->priv->tz_monitor = NULL;
620+ }
621+
622+ if (self->priv->desktop_settings != NULL) {
623+ g_object_unref (self->priv->desktop_settings);
624+ self->priv->desktop_settings = NULL;
625+ }
626+
627+ G_OBJECT_CLASS (gnome_wall_clock_parent_class)->dispose (object);
628+}
629+
630+static void
631+gnome_wall_clock_finalize (GObject *object)
632+{
633+ GnomeWallClock *self = GNOME_WALL_CLOCK (object);
634+
635+ g_free (self->priv->clock_string);
636+
637+ G_OBJECT_CLASS (gnome_wall_clock_parent_class)->finalize (object);
638+}
639+
640+static void
641+gnome_wall_clock_get_property (GObject *gobject,
642+ guint prop_id,
643+ GValue *value,
644+ GParamSpec *pspec)
645+{
646+ GnomeWallClock *self = GNOME_WALL_CLOCK (gobject);
647+
648+ switch (prop_id)
649+ {
650+ case PROP_CLOCK:
651+ g_value_set_string (value, self->priv->clock_string);
652+ break;
653+ default:
654+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
655+ break;
656+ }
657+}
658+
659+static void
660+gnome_wall_clock_class_init (GnomeWallClockClass *klass)
661+{
662+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
663+
664+ gobject_class->get_property = gnome_wall_clock_get_property;
665+ gobject_class->dispose = gnome_wall_clock_dispose;
666+ gobject_class->finalize = gnome_wall_clock_finalize;
667+
668+ /**
669+ * GnomeWallClock:clock:
670+ *
671+ * A formatted string representing the current clock display.
672+ */
673+ g_object_class_install_property (gobject_class,
674+ PROP_CLOCK,
675+ g_param_spec_string ("clock",
676+ "",
677+ "",
678+ NULL,
679+ G_PARAM_READABLE));
680+
681+
682+ g_type_class_add_private (gobject_class, sizeof (GnomeWallClockPrivate));
683+}
684+
685+static gboolean
686+update_clock (gpointer data)
687+{
688+ GnomeWallClock *self = data;
689+ GDesktopClockFormat clock_format;
690+ const char *format_string;
691+ gboolean show_date;
692+ gboolean show_seconds;
693+ GSource *source;
694+ GDateTime *now;
695+ GDateTime *expiry;
696+
697+ clock_format = g_settings_get_enum (self->priv->desktop_settings, "clock-format");
698+ show_date = g_settings_get_boolean (self->priv->desktop_settings, "clock-show-date");
699+ show_seconds = g_settings_get_boolean (self->priv->desktop_settings, "clock-show-seconds");
700+
701+ now = g_date_time_new_now_local ();
702+ if (show_seconds)
703+ expiry = g_date_time_add_seconds (now, 1);
704+ else
705+ expiry = g_date_time_add_seconds (now, 60 - g_date_time_get_second (now));
706+
707+ if (self->priv->clock_update_id)
708+ g_source_remove (self->priv->clock_update_id);
709+
710+ source = _gnome_datetime_source_new (now, expiry, TRUE);
711+ g_source_set_priority (source, G_PRIORITY_HIGH);
712+ g_source_set_callback (source, update_clock, self, NULL);
713+ self->priv->clock_update_id = g_source_attach (source, NULL);
714+ g_source_unref (source);
715+
716+ if (clock_format == G_DESKTOP_CLOCK_FORMAT_24H) {
717+ if (show_date)
718+ /* Translators: This is the time format with date used
719+ in 24-hour mode. */
720+ format_string = show_seconds ? _("%a %b %e, %R:%S")
721+ : _("%a %b %e, %R");
722+ else
723+ /* Translators: This is the time format without date used
724+ in 24-hour mode. */
725+ format_string = show_seconds ? _("%a %R:%S")
726+ : _("%a %R");
727+ } else {
728+ if (show_date)
729+ /* Translators: This is a time format with date used
730+ for AM/PM. */
731+ format_string = show_seconds ? _("%a %b %e, %l:%M:%S %p")
732+ : _("%a %b %e, %l:%M %p");
733+ else
734+ /* Translators: This is a time format without date used
735+ for AM/PM. */
736+ format_string = show_seconds ? _("%a %l:%M:%S %p")
737+ : _("%a %l:%M %p");
738+ }
739+
740+ g_free (self->priv->clock_string);
741+ self->priv->clock_string = g_date_time_format (now, format_string);
742+
743+ g_date_time_unref (now);
744+ g_date_time_unref (expiry);
745+
746+ g_object_notify ((GObject*)self, "clock");
747+
748+ return FALSE;
749+}
750+
751+static void
752+on_schema_change (GSettings *schema,
753+ const char *key,
754+ gpointer user_data)
755+{
756+ update_clock (user_data);
757+}
758+
759+static void
760+on_tz_changed (GFileMonitor *monitor,
761+ GFile *file,
762+ GFile *other_file,
763+ GFileMonitorEvent *event,
764+ gpointer user_data)
765+{
766+ update_clock (user_data);
767+}
768+
769+const char *
770+gnome_wall_clock_get_clock (GnomeWallClock *clock)
771+{
772+ return clock->priv->clock_string;
773+}
774
775=== added file 'src/gnome-wall-clock.h'
776--- src/gnome-wall-clock.h 1970-01-01 00:00:00 +0000
777+++ src/gnome-wall-clock.h 2011-09-30 00:00:28 +0000
778@@ -0,0 +1,62 @@
779+/* gnome-tz-monitor.h - fade window background between two surfaces
780+
781+ Copyright 2008, Red Hat, Inc.
782+ Copyright 2011, Red Hat, Inc.
783+
784+ This file is part of the Gnome Library.
785+
786+ The Gnome Library is free software; you can redistribute it and/or
787+ modify it under the terms of the GNU Library General Public License as
788+ published by the Free Software Foundation; either version 2 of the
789+ License, or (at your option) any later version.
790+
791+ The Gnome Library is distributed in the hope that it will be useful,
792+ but WITHOUT ANY WARRANTY; without even the implied warranty of
793+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
794+ Library General Public License for more details.
795+
796+ You should have received a copy of the GNU Library General Public
797+ License along with the Gnome Library; see the file COPYING.LIB. If not,
798+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
799+ Boston, MA 02111-1307, USA.
800+
801+ Author: Colin Walters <walters@verbum.org>
802+*/
803+
804+#ifndef __GNOME_WALL_CLOCK_H__
805+#define __GNOME_WALL_CLOCK_H__
806+
807+#include <gio/gio.h>
808+
809+G_BEGIN_DECLS
810+
811+#define GNOME_TYPE_WALL_CLOCK (gnome_wall_clock_get_type ())
812+#define GNOME_WALL_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_WALL_CLOCK, GnomeWallClock))
813+#define GNOME_WALL_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_WALL_CLOCK, GnomeWallClockClass))
814+#define GNOME_IS_WALL_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_WALL_CLOCK))
815+#define GNOME_IS_WALL_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_WALL_CLOCK))
816+#define GNOME_WALL_CLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_WALL_CLOCK, GnomeWallClockClass))
817+
818+typedef struct _GnomeWallClockPrivate GnomeWallClockPrivate;
819+typedef struct _GnomeWallClock GnomeWallClock;
820+typedef struct _GnomeWallClockClass GnomeWallClockClass;
821+
822+struct _GnomeWallClock
823+{
824+ GObject parent_object;
825+
826+ GnomeWallClockPrivate *priv;
827+};
828+
829+struct _GnomeWallClockClass
830+{
831+ GObjectClass parent_class;
832+};
833+
834+GType gnome_wall_clock_get_type (void);
835+
836+const char * gnome_wall_clock_get_clock (GnomeWallClock *clock);
837+
838+G_END_DECLS
839+
840+#endif
841
842=== modified file 'src/indicator-datetime.c'
843--- src/indicator-datetime.c 2011-09-21 20:19:53 +0000
844+++ src/indicator-datetime.c 2011-09-30 00:00:28 +0000
845@@ -48,6 +48,7 @@
846 #include "utils.h"
847 #include "dbus-shared.h"
848 #include "settings-shared.h"
849+#include "gnome-wall-clock.h"
850
851
852 #define INDICATOR_DATETIME_TYPE (indicator_datetime_get_type ())
853@@ -72,7 +73,6 @@
854
855 struct _IndicatorDatetimePrivate {
856 GtkLabel * label;
857- guint timer;
858
859 gchar * time_string;
860
861@@ -101,8 +101,11 @@
862 GList * timezone_items;
863
864 GSettings * settings;
865+ GSettings * gnome_settings;
866
867 GtkSizeGroup * indicator_right_group;
868+
869+ GnomeWallClock *clock;
870 };
871
872 /* Enum for the properties so that they can be quickly
873@@ -166,7 +169,7 @@
874 static gchar * generate_format_string_now (IndicatorDatetime * self);
875 static void update_label (IndicatorDatetime * io, GDateTime ** datetime);
876 static void guess_label_size (IndicatorDatetime * self);
877-static void setup_timer (IndicatorDatetime * self, GDateTime * datetime);
878+static void on_clock_changed (GnomeWallClock *clock, GParamSpec *pspec, gpointer user_data);
879 static void update_time (IndicatorDatetime * self);
880 static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
881 static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
882@@ -293,7 +296,6 @@
883 IndicatorDatetimePrivate);
884
885 self->priv->label = NULL;
886- self->priv->timer = 0;
887
888 self->priv->idle_measure = 0;
889 self->priv->max_width = 0;
890@@ -362,6 +364,11 @@
891 g_warning("Unable to get settings for '" SETTINGS_INTERFACE "'");
892 }
893
894+ self->priv->gnome_settings = g_settings_new ("org.gnome.desktop.interface");
895+
896+ self->priv->clock = g_object_new (GNOME_TYPE_WALL_CLOCK, NULL);
897+ g_signal_connect (self->priv->clock, "notify::clock", G_CALLBACK (on_clock_changed), self);
898+
899 self->priv->sm = indicator_service_manager_new_version(SERVICE_NAME, SERVICE_VERSION);
900 self->priv->indicator_right_group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL));
901
902@@ -433,9 +440,9 @@
903 self->priv->label = NULL;
904 }
905
906- if (self->priv->timer != 0) {
907- g_source_remove(self->priv->timer);
908- self->priv->timer = 0;
909+ if (self->priv->clock != NULL) {
910+ g_object_unref (self->priv->clock);
911+ self->priv->clock = NULL;
912 }
913
914 if (self->priv->idle_measure != 0) {
915@@ -562,7 +569,7 @@
916 if (newval != self->priv->time_mode) {
917 update = TRUE;
918 self->priv->time_mode = newval;
919- setup_timer(self, NULL);
920+ update_time (self);
921 }
922 break;
923 }
924@@ -571,8 +578,11 @@
925 self->priv->show_seconds = !self->priv->show_seconds;
926 if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) {
927 update = TRUE;
928- setup_timer(self, NULL);
929+ update_time (self);
930 }
931+ g_settings_set_boolean (self->priv->gnome_settings,
932+ "clock-show-seconds",
933+ self->priv->show_seconds);
934 }
935 break;
936 }
937@@ -606,8 +616,11 @@
938 self->priv->custom_show_seconds = (time_mask & STRFTIME_MASK_SECONDS);
939 if (self->priv->time_mode == SETTINGS_TIME_CUSTOM) {
940 update = TRUE;
941- setup_timer(self, NULL);
942+ update_time (self);
943 }
944+ g_settings_set_boolean (self->priv->gnome_settings,
945+ "clock-show-seconds",
946+ self->priv->show_seconds);
947 }
948 break;
949 }
950@@ -831,12 +844,21 @@
951 update_label(self, &dt);
952 timezone_update_all_labels(self);
953 if (dt != NULL) {
954- setup_timer(self, dt);
955 g_date_time_unref(dt);
956 }
957 return;
958 }
959
960+static void
961+on_clock_changed (GnomeWallClock *clock,
962+ GParamSpec *pspec,
963+ gpointer user_data)
964+{
965+ IndicatorDatetime *self = INDICATOR_DATETIME (user_data);
966+
967+ update_time (self);
968+}
969+
970 /* Receives all signals from the service, routed to the appropriate functions */
971 static void
972 receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name,
973@@ -851,54 +873,6 @@
974 return;
975 }
976
977-/* Runs every minute and updates the time */
978-gboolean
979-timer_func (gpointer user_data)
980-{
981- IndicatorDatetime * self = INDICATOR_DATETIME(user_data);
982- self->priv->timer = 0;
983- GDateTime * dt = NULL;
984- update_label(self, &dt);
985- timezone_update_all_labels(self);
986- if (dt != NULL) {
987- setup_timer(self, dt);
988- g_date_time_unref(dt);
989- }
990- return FALSE;
991-}
992-
993-/* Configure the timer to run the next time through */
994-static void
995-setup_timer (IndicatorDatetime * self, GDateTime * datetime)
996-{
997- gboolean unref = FALSE;
998-
999- if (self->priv->timer != 0) {
1000- g_source_remove(self->priv->timer);
1001- self->priv->timer = 0;
1002- }
1003-
1004- if (self->priv->show_seconds ||
1005- (self->priv->time_mode == SETTINGS_TIME_CUSTOM && self->priv->custom_show_seconds)) {
1006- self->priv->timer = g_timeout_add_full(G_PRIORITY_HIGH, 999, timer_func, self, NULL);
1007- } else {
1008- if (datetime == NULL) {
1009- datetime = g_date_time_new_now_local();
1010- unref = TRUE;
1011- }
1012-
1013- /* Plus 2 so we're just after the minute, don't want to be early. */
1014- gint seconds = (gint)g_date_time_get_seconds(datetime);
1015- self->priv->timer = g_timeout_add_seconds(60 - seconds + 2, timer_func, self);
1016-
1017- if (unref) {
1018- g_date_time_unref(datetime);
1019- }
1020- }
1021-
1022- return;
1023-}
1024-
1025 /* Does a quick meausre of how big the string is in
1026 pixels with a Pango layout */
1027 static gint
1028@@ -1521,10 +1495,6 @@
1029 gtk_widget_set_visible(GTK_WIDGET (self->priv->label), self->priv->show_clock);
1030 }
1031
1032- if (self->priv->timer == 0) {
1033- setup_timer(self, NULL);
1034- }
1035-
1036 return self->priv->label;
1037 }
1038

Subscribers

People subscribed via source and target branches