Author: juha
Date: 2008-11-11 07:05:34 +0000 (Tue, 11 Nov 2008)
New Revision: 28724

Modified:
   xfcalendar/trunk/configure.in.in
   xfcalendar/trunk/panel-plugin/oc_config.c
   xfcalendar/trunk/panel-plugin/orageclock.c
   xfcalendar/trunk/panel-plugin/orageclock.h
Log:
fixed bug in orageclock, where time could be wrong 
after hibernate or suspend.


Modified: xfcalendar/trunk/configure.in.in
===================================================================
--- xfcalendar/trunk/configure.in.in    2008-11-11 05:17:12 UTC (rev 28723)
+++ xfcalendar/trunk/configure.in.in    2008-11-11 07:05:34 UTC (rev 28724)
@@ -9,7 +9,7 @@
 dnl
 
 dnl Version information
-m4_define([orage_version], [4.5.92.2-svn])
+m4_define([orage_version], [4.5.92.3-svn])
 
 m4_define([gtk_minimum_version], [2.6.0])
 m4_define([xfce_minimum_version], [4.4.0])

Modified: xfcalendar/trunk/panel-plugin/oc_config.c
===================================================================
--- xfcalendar/trunk/panel-plugin/oc_config.c   2008-11-11 05:17:12 UTC (rev 
28723)
+++ xfcalendar/trunk/panel-plugin/oc_config.c   2008-11-11 07:05:34 UTC (rev 
28724)
@@ -148,6 +148,12 @@
     oc_show_line_set(clock, 2);
 }
 
+static void oc_hib_timing_toggled(GtkToggleButton *cb, Clock *clock)
+{
+    clock->hib_timing = gtk_toggle_button_get_active(cb);
+    oc_hib_timing_set(clock);
+}
+
 static gboolean oc_line_changed(GtkWidget *entry, GdkEventKey *key
         , GString *data)
 {
@@ -276,7 +282,7 @@
     gtk_container_set_border_width(GTK_CONTAINER(frame), 6);
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, FALSE, FALSE, 0);
 
-    table = gtk_table_new(5, 3, FALSE);
+    table = gtk_table_new(6, 3, FALSE);
     gtk_container_set_border_width(GTK_CONTAINER(table), 10);
     gtk_table_set_row_spacings(GTK_TABLE(table), 6);
     gtk_table_set_col_spacings(GTK_TABLE(table), 6);
@@ -380,6 +386,15 @@
     oc_table_add(table, entry, 1, 4);
     g_signal_connect(entry, "key-release-event", G_CALLBACK(oc_line_changed)
             , clock->tooltip_data);
+    
+    /* special timing for SUSPEND/HIBERNATE */
+    cb = gtk_check_button_new_with_mnemonic(_("fix time after 
suspend/hibernate"));
+    oc_table_add(table, cb, 1, 5);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb), clock->hib_timing);
+    gtk_tooltips_set_tip(clock->tips, GTK_WIDGET(cb),
+            _("You only need this if you do short term (less than 5 hours) 
suspend or hibernate and your visible time does not include seconds. Under 
these circumstances it is possible that Orageclock shows time inaccurately 
unless you have this selected. (Selecting this prevents cpu and interrupt 
saving features from working.)")
+            , NULL);
+    g_signal_connect(cb, "toggled", G_CALLBACK(oc_hib_timing_toggled), clock);
 
     /* Instructions */
     hbox = gtk_hbox_new(FALSE, 0);
@@ -411,7 +426,6 @@
     
     clock->interval = 200; /* 0,2 sec, so that we can show quick feedback
                             * on the panel */
-    oc_disable_tuning(clock);
     oc_start_timer(clock);
     dlg = gtk_dialog_new_with_buttons(_("Properties"), 
             GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(plugin))),

Modified: xfcalendar/trunk/panel-plugin/orageclock.c
===================================================================
--- xfcalendar/trunk/panel-plugin/orageclock.c  2008-11-11 05:17:12 UTC (rev 
28723)
+++ xfcalendar/trunk/panel-plugin/orageclock.c  2008-11-11 07:05:34 UTC (rev 
28724)
@@ -111,198 +111,148 @@
 
 static gboolean oc_get_time_delay(Clock *clock)
 {
+    /* now we really start the clock */
+    oc_get_time(clock);
     clock->timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
             , clock->interval, (GSourceFunc)oc_get_time, clock, NULL);
-    oc_get_time(clock);
     return(FALSE); /* this is one time only timer */
 }
 
 gboolean oc_start_timer(Clock *clock)
 {
     time_t t;
-    gint   delay_time =  0;
-    /* if we are using longer than 1 minute (= 60000) interval, we need
+    gint delay_time; /* this is used to set the clock start tie correct */
+
+    /*
+    g_message("oc_start_timer: (%s) interval %d  %d:%d:%d", 
clock->tooltip_prev, clock->interval, clock->now.tm_hour, clock->now.tm_min, 
clock->now.tm_sec);
+    */
+    /* stop the clock refresh since we will start it again here soon */
+    if (clock->timeout_id) {
+        g_source_remove(clock->timeout_id);
+        clock->timeout_id = 0;
+    }
+    oc_get_time(clock); /* put time on the clock and also fill clock->now */
+    /* if we are using longer than 1 second (== 1000) interval, we need
      * to delay the first start so that clock changes when minute or hour
      * changes */
-
-    oc_get_time(clock);
-    time(&t);
-    localtime_r(&t, &clock->now);
-    if (clock->interval >= 60000) {
-        if (clock->interval >= 3600000) /* match to next full hour */
-            delay_time = (clock->interval -
+    if (clock->interval <= 1000) /* no adjustment needed, we show seconds */
+        delay_time = 100; /* small delay since 0 is a bit scary */
+    else if (clock->interval <= 60000) /* adjust to next full minute */
+        delay_time = (clock->interval - clock->now.tm_sec*1000);
+    else /* if (clock->interval <= 3600000) */ /* adjust to next full hour */
+        delay_time = (clock->interval -
                     (clock->now.tm_min*60000 + clock->now.tm_sec*1000));
-        else /* match to next full minute */
-            delay_time = (clock->interval - clock->now.tm_sec*1000);
-    }
+
     if (clock->delay_timeout_id) {
         g_source_remove(clock->delay_timeout_id);
         clock->delay_timeout_id = 0;
     }
-    if (clock->timeout_id) {
-        g_source_remove(clock->timeout_id);
-        clock->timeout_id = 0;
-    }
     clock->delay_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
             , delay_time, (GSourceFunc)oc_get_time_delay, clock, NULL);
+
     /* if we have longer than 1 sec timer, we need to reschedule 
-     * it regularly since it will fall down slowly but surely, so
+     * it regularly since it will fall wrong slowly but surely, so
      * we keep this running. */
-    if (clock->interval >= 60000) {
-        if (delay_time > 60000)
-        /* let's run it once in case we happened to kill it
-           just when it was supposed to start */
-            oc_get_time(clock); 
-        return(TRUE);
-    }
-    else
-        return(FALSE);
+    return(TRUE);
 }
 
-static void oc_end_tuning(Clock *clock)
+gboolean oc_check_if_same(Clock *clock, int diff)
 {
-    /* if we have longer than 1 sec timer, we need to reschedule 
-     * it regularly since it will fall down slowly but surely */
-    if (clock->adjust_timeout_id) {
-        g_source_remove(clock->adjust_timeout_id);
-        clock->adjust_timeout_id = 0;
-    }
-    if (clock->interval >= 60000) { /* resync it after each 4 hours */
-        oc_start_timer(clock);
-        clock->adjust_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
-                , 4*60*60*1000, (GSourceFunc)oc_start_timer, clock, NULL);
-    }
-    g_free(clock->tune);
-    clock->tune = NULL;
-}
-
-static gboolean oc_next_level_tuning(Clock *clock)
-{
-    TimeTuning *tune = clock->tune;
-    gboolean continue_tuning = TRUE;
-
-    if (clock->interval == OC_CONFIG_INTERVAL) /* setup active => no changes */
-        return(FALSE);
-    switch (tune->level) {
-        case 0: /* second now; let's set interval to minute */
-            clock->interval = 60*1000; 
-            break;
-        case 1: /* minute now; let's set it to hour */
-            clock->interval = 60*60*1000; 
-            break;
-        default: /* no point tune more */
-            break;
-    }
-    if (tune->level < 2) {
-        tune->level++;
-        oc_start_timer(clock);
-        oc_start_tuning(clock);
-    }
-    else {
-        continue_tuning = FALSE;
-        oc_end_tuning(clock);
-    }
-    return(continue_tuning);
-}
-
-static gboolean oc_tune_time(Clock *clock)
-{
-    /* idea is that we compare the panel string three times and 
-     * if all of those are the same, we can tune the timer since we know 
-     * that we do not have to check it so often. Time in panel plugin is
-     * not changing anyway. So we adjust the timers and check again */
-    gboolean continue_tuning = TRUE;
-    TimeTuning *tune = clock->tune;
-
-    if (clock->interval == OC_CONFIG_INTERVAL) /* setup active => no changes */
-        return(FALSE);
-    switch (tune->cnt) {
-        case 0: /* first time we come here */
-            strncpy(tune->prev[0], clock->line[0].prev, OC_MAX_LINE_LENGTH);
-            strncpy(tune->prev[1], clock->line[1].prev, OC_MAX_LINE_LENGTH);
-            strncpy(tune->prev[2], clock->line[2].prev, OC_MAX_LINE_LENGTH);
-            strncpy(tune->tooltip_prev, 
clock->tooltip_prev,OC_MAX_LINE_LENGTH);
-            break;
-        case 1:
-        case 2:
-        case 3: /* FIXME: two may be enough ?? */
-            if (strncmp(tune->prev[0], clock->line[0].prev, OC_MAX_LINE_LENGTH)
-            ||  strncmp(tune->prev[1], clock->line[1].prev, OC_MAX_LINE_LENGTH)
-            ||  strncmp(tune->prev[2], clock->line[2].prev, OC_MAX_LINE_LENGTH)
-            ||  strncmp(tune->tooltip_prev, clock->tooltip_prev
-                    ,OC_MAX_LINE_LENGTH)) {
-                /* time has changed. But it may change due to bigger time
-                 * change. For example if we are checking seconds and time
-                 * only shows minutes, this can change if hour happens to
-                 * change. So we need to check the change twice to be sure */
-                if (tune->changed_once) { /* this is the second trial already 
*/
-                    continue_tuning = FALSE;
-                    oc_end_tuning(clock);
+    /* we compare if clock would change after diff seconds */
+    /* instead of waiting for the time to really pass, we just move the clock
+     * and see what would happen in the future. No need to wait for hours. */
+    time_t  t, t_next;
+    struct tm tm, tm_next;
+    char    res[OC_MAX_LINE_LENGTH-1], res_next[OC_MAX_LINE_LENGTH-1];
+    int     i, max_len;
+    ClockLine *line;
+    gboolean same_time = TRUE, first_check = TRUE, result_known = FALSE;
+    
+    max_len = sizeof(res); 
+    while (!result_known) {
+        time(&t);
+        t_next = t + diff;  /* diff secs forward */
+        localtime_r(&t, &tm);
+        localtime_r(&t_next, &tm_next);
+        for (i = 0; (i < OC_MAX_LINES) && same_time; i++) {
+            line = &clock->line[i];
+            if (line->show) {
+                utf8_strftime(res, max_len, line->data->str, &tm);
+                utf8_strftime(res_next, max_len, line->data->str, &tm_next);
+                if (strcmp(res,  res_next)) { /* differ */
+                    same_time = FALSE;
                 }
-                else { /* need to try again */
-                    tune->changed_once = TRUE;
-                    tune->cnt = -1; /* this gets incremented to 0 below */
-                }
             }
-            break;
-        default:
-            break;
-    }
-    if (continue_tuning) {
-        if (tune->cnt == 3) 
-            continue_tuning = oc_next_level_tuning(clock);
-        else 
-            tune->cnt++;
-    }
+        }
+        /* Need to check also tooltip */
+        if (same_time) { /* we only check tooltip if needed */
+            utf8_strftime(res, max_len, clock->tooltip_data->str, &tm);
+            utf8_strftime(res_next, max_len, 
clock->tooltip_data->str,&tm_next);
+            if (strcmp(res,  res_next)) { /* differ */
+                same_time = FALSE;
+            }
+        }
 
-    return(continue_tuning);
+        if (!same_time) {
+            if (first_check) {
+                /* change detected, but it can be that bigger unit 
+                 * like hour or day happened to change, so we need to check 
+                 * again to be sure */
+                first_check = FALSE;
+                same_time = TRUE;
+            }
+            else { /* second check, now we are sure the clock has changed */
+                result_known = TRUE;   /* no need to check more */
+            }
+        }
+        else { /* clock did not change */
+            result_known = TRUE;   /* no need to check more */
+        }
+    }
+    return(same_time);
 }
 
-void oc_disable_tuning(Clock *clock)
+void oc_tune_interval(Clock *clock)
 {
-    TimeTuning *tune = clock->tune;
+    gboolean same_time;
 
-    if (tune == NULL)
-        return;
-    if (tune->timeout_id) {
-        g_source_remove(tune->timeout_id);
-        tune->timeout_id = 0;
-    }
     if (clock->adjust_timeout_id) {
         g_source_remove(clock->adjust_timeout_id);
         clock->adjust_timeout_id = 0;
     }
-}
-
-void oc_start_tuning(Clock *clock)
-{
-    TimeTuning *tune = clock->tune;
-
-    if (clock->interval == OC_CONFIG_INTERVAL) /* setup active => no changes */
-        return;
-    tune->cnt = 0;
-    tune->changed_once = FALSE;
-    if (tune->timeout_id) {
-        g_source_remove(tune->timeout_id);
-        tune->timeout_id = 0;
+    /* check if clock changes after 2 secs */
+    if ((same_time = oc_check_if_same(clock, 2))) { /* Continue checking */
+        /* We know now that clock does not change every second. 
+         * Let's check 2 minutes next: */
+        if ((same_time = oc_check_if_same(clock, 2*60))) {
+            /* We know now that clock does not change every minute. 
+             * We could check hours next, but cpu saving between 1 hour and 24
+             * hours would be minimal. But keeping 24 hour wake up time clock
+             * in accurate time would be much more difficult, so we end here 
+             * and schedule clock to fire every hour. */
+            clock->interval = 3600000;
+        }
+        else { /* we schedule clock to fire every minute */
+            clock->interval = 60000;
+        }
+        /* Our timer runs slow ( every minute or every hour only), so we need
+         * to resync time regularly (every 4 hours) to keep clock in time: */
+        clock->adjust_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
+                , 4*60*60*1000, (GSourceFunc)oc_start_timer, clock, NULL);
     }
-    tune->timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
-            , 2*clock->interval, (GSourceFunc)oc_tune_time, clock, NULL);
 }
 
 void oc_init_timer(Clock *clock)
 {
     clock->interval = OC_BASE_INTERVAL;
-    if (clock->tune == NULL)
-        clock->tune = g_new0(TimeTuning, 1);
-    clock->tune->level = 0;
+    oc_get_time(clock); /* update clock once */
+    if (!clock->hib_timing) /* using suspend/hibernate, do not tune time */
+        oc_tune_interval(clock);
     oc_start_timer(clock);
-    oc_start_tuning(clock);
 }
 
 static void oc_update_size(Clock *clock, int size)
 {
-    /* keep in sync with systray */
     if (size > 26) {
         gtk_container_set_border_width(GTK_CONTAINER(clock->frame), 2);
         size -= 3;
@@ -508,6 +458,8 @@
     if ((ret = xfce_rc_read_entry(rc, "tooltip", NULL)))
         g_string_assign(clock->tooltip_data, ret); 
 
+    clock->hib_timing = xfce_rc_read_bool_entry(rc, "hib_timing", FALSE);
+
     xfce_rc_close(rc);
 }
 
@@ -587,6 +539,8 @@
 
     xfce_rc_write_entry(rc, "tooltip",  clock->tooltip_data->str);
 
+    xfce_rc_write_bool_entry(rc, "hib_timing", clock->hib_timing);
+
     xfce_rc_close(rc);
 }
 
@@ -641,10 +595,11 @@
      */
     clock->tooltip_data = g_string_new(_("%A %d %B %Y/%V"));
 
+    clock->hib_timing = FALSE;
+
     clock->tips = gtk_tooltips_new();
     g_object_ref(clock->tips);
     gtk_object_sink(GTK_OBJECT(clock->tips));
-    oc_init_timer(clock);
         
     return(clock);
 }
@@ -655,6 +610,10 @@
             , clock->show_frame ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
 }
 
+void oc_hib_timing_set(Clock *clock)
+{
+}
+
 void oc_fg_set(Clock *clock)
 {
     GdkColor *fg = NULL;
@@ -754,6 +713,7 @@
     gtk_container_add(GTK_CONTAINER(plugin), clock->ebox);
 
     oc_read_rc_file(plugin, clock);
+    oc_init_timer(clock);
 
     oc_show_frame_set(clock);
     oc_fg_set(clock);

Modified: xfcalendar/trunk/panel-plugin/orageclock.h
===================================================================
--- xfcalendar/trunk/panel-plugin/orageclock.h  2008-11-11 05:17:12 UTC (rev 
28723)
+++ xfcalendar/trunk/panel-plugin/orageclock.h  2008-11-11 07:05:34 UTC (rev 
28724)
@@ -20,19 +20,9 @@
 #define OC_NAME "orageclock panel plugin"
 #define OC_MAX_LINES 3 /* changing this causes trouble. don't do it */
 #define OC_MAX_LINE_LENGTH 100 
-#define OC_BASE_INTERVAL 1000  /* best accurance of the clock */
+#define OC_BASE_INTERVAL 1000  /* best accurance of the clock = 1 sec */
 #define OC_CONFIG_INTERVAL 200 /* special fast interval used in setup */
 
-typedef struct _timetuning
-{
-    gint  level; /* 0 = seconds, 1 = minutes, 2 = hours */
-    gint  cnt;
-    gboolean changed_once; 
-    gint  timeout_id;
-    gchar prev[OC_MAX_LINES][OC_MAX_LINE_LENGTH+1];
-    gchar tooltip_prev[OC_MAX_LINE_LENGTH+1];
-} TimeTuning;
-
 typedef struct _clockline
 {
     GtkWidget *label;
@@ -64,15 +54,14 @@
     ClockLine  line[OC_MAX_LINES];
     GString   *tooltip_data;
     gchar      tooltip_prev[OC_MAX_LINE_LENGTH+1];
+    gboolean   hib_timing;
 
     GtkTooltips *tips;
-    int timeout_id;
+    int timeout_id;  /* timer id for the clock */
     int delay_timeout_id;
     int adjust_timeout_id;
     int interval;
     struct tm   now;
-
-    TimeTuning  *tune;
 } Clock;
 
 void oc_properties_dialog(XfcePanelPlugin *plugin, Clock *clock);
@@ -84,9 +73,8 @@
 void oc_timezone_set(Clock *clock);
 void oc_show_line_set(Clock *clock, gint lno);
 void oc_line_font_set(Clock *clock, gint lno);
+void oc_hib_timing_set(Clock *clock);
 void oc_write_rc_file(XfcePanelPlugin *plugin, Clock *clock);
 gboolean oc_start_timer(Clock *clock);
-void oc_start_tuning(Clock *clock);
-void oc_disable_tuning(Clock *clock);
 void oc_init_timer(Clock *clock);
 

_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to