diff -u trunk/panel-plugin/datetime.c exp3/panel-plugin/datetime.c --- trunk/panel-plugin/datetime.c 2008-06-08 19:17:04.000000000 -0700 +++ exp3/panel-plugin/datetime.c 2008-06-12 11:24:50.000000000 -0700 @@ -51,6 +51,20 @@ } /* + * Compute the wake interval, + * which is the time remaining from the current time + * to the next larger integral multiple of the update interval. + * Setting a timer to this value schedules the next update + * to occur on the next second or minute + * when the given update interval is 1000 or 60000 milliseconds, respectively. + */ +static inline guint datetime_wake_interval_from_current_time(const GTimeVal current_time, + const guint update_interval_ms) +{ + return (update_interval_ms - datetime_gtimeval_to_ms(current_time) % update_interval_ms); +} + +/* * Get date/time string */ gchar * datetime_do_utf8strftime(const char *format, const struct tm *tm) @@ -109,21 +123,15 @@ } /* - * set date and time labels + * set date and time labels when timer expires */ -gboolean datetime_update(t_datetime *datetime) +static gboolean datetime_update1(t_datetime *datetime) { GTimeVal timeval; gchar *utf8str; struct tm *current; guint wake_interval; /* milliseconds to next update */ - /* stop timer */ - if (datetime->timeout_id) - { - g_source_remove(datetime->timeout_id); - } - g_get_current_time(&timeval); current = localtime((time_t *)&timeval.tv_sec); @@ -143,31 +151,75 @@ g_free(utf8str); } - /* - * Compute the time to the next update and start the timer. - * The wake interval is the time remaining - * to the next larger integral multiple of the update interval. - * Setting the timer to this value schedules the next update - * to occur on the next second or minute - * when the update interval is 1 or 60 seconds, respectively. - */ - wake_interval = datetime->update_interval - datetime_gtimeval_to_ms(timeval) % datetime->update_interval; - datetime->timeout_id = g_timeout_add(wake_interval, (GSourceFunc) datetime_update, datetime); + /* Compute the time to the next update and start the timer. */ + wake_interval = datetime_wake_interval_from_current_time(timeval, datetime->update_interval); + datetime->timeout_id = g_timeout_add(wake_interval, (GSourceFunc) datetime_update1, datetime); - return TRUE; + /* remove previous timer */ + return FALSE; } +/* + * set update intervals for the plugin and the tooltip + * start periodic updates + */ +void datetime_update(t_datetime *datetime) +{ + /* a custom date format could specify seconds */ + gboolean date_has_seconds = datetime_format_has_seconds(datetime->date_format); + gboolean time_has_seconds = datetime_format_has_seconds(datetime->time_format); + gboolean has_seconds; + + /* set update interval for the date/time displayed in the panel */ + switch(datetime->layout) + { + case LAYOUT_DATE: + has_seconds = date_has_seconds; + break; + case LAYOUT_TIME: + has_seconds = time_has_seconds; + break; + default: + has_seconds = date_has_seconds || time_has_seconds; + break; + } + /* 1000 ms == 1 second; 60000 ms == 1 minute */ + datetime->update_interval = has_seconds ? 1000 : 60000; + #if USE_GTK_TOOLTIP_API + /* set update interval for the date/time displayed in the tooltip */ + switch(datetime->layout) + { + case LAYOUT_DATE: + has_seconds = time_has_seconds; + break; + case LAYOUT_TIME: + has_seconds = date_has_seconds; + break; + default: + /* tooltips are disabled in this case, so set to a definite value */ + has_seconds = FALSE; + break; + } + datetime->tooltip_update_interval = has_seconds ? 1000 : 60000; +#endif + + /* start periodic updates */ + datetime_update1(datetime); +} + +#if USE_GTK_TOOLTIP_API +/* + * tooltip timer handler registered in datetime_query_tooltip() + */ static gboolean datetime_tooltip_timer(t_datetime *datetime) { - - /* flag to datetime_query_tooltip that there is no longer an active timeout */ + /* The timer has expired, so datetime_query_tooltip() does not need to remove it. */ datetime->tooltip_timeout_id = 0; /* - * Run datetime_query_tooltip if the mouse is still there. - * If it is run, it'll register *this* function to be called after another - * timeout. If not, *this* function won't run again. + * Trigger a "query-tooltip" event, + * which is handled by datetime_query_tooltip(). */ gtk_widget_trigger_tooltip_query(GTK_WIDGET(datetime->button)); @@ -175,6 +227,13 @@ return FALSE; } +/* + * "query-tooltip" event handler + * If tooltips are enabled, + * this handler is called when the cursor enters the plugin's button rectangle or + * the cursor moves while in the rectangle or + * indirectly by datetime_tooltip_timer() via gtk_widget_trigger_tooltip_query(). + */ static gboolean datetime_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, @@ -185,6 +244,16 @@ struct tm *current; gchar *utf8str; gchar *format = NULL; + guint wake_interval; /* milliseconds to next update */ + + DBG("enter"); + + /* stop timer */ + if (datetime->tooltip_timeout_id != 0) + { + g_source_remove(datetime->tooltip_timeout_id); + datetime->tooltip_timeout_id = 0; + } switch(datetime->layout) { @@ -195,6 +264,8 @@ format = datetime->time_format; break; default: + /* Tooltips are disabled in this case, so it should not occur. */ + DBG("tooltips are disabled"); break; } @@ -208,16 +279,10 @@ gtk_tooltip_set_text(tooltip, utf8str); g_free(utf8str); - /* if there is no active timeout to update the tooltip, register one */ - if (!datetime->tooltip_timeout_id) - { - /* - * I think we can afford to inefficiently poll every - * second while the user keeps the mouse here. - */ - datetime->tooltip_timeout_id = g_timeout_add(1000, - (GSourceFunc) datetime_tooltip_timer, datetime); - } + /* Compute the time to the next update and start the timer. */ + wake_interval = datetime_wake_interval_from_current_time(timeval, datetime->tooltip_update_interval); + datetime->tooltip_timeout_id = g_timeout_add(wake_interval, + (GSourceFunc) datetime_tooltip_timer, datetime); return TRUE; } @@ -452,23 +517,12 @@ } #if USE_GTK_TOOLTIP_API - /* update tooltip handler */ - if (datetime->tooltip_handler_id) - { - g_signal_handler_disconnect(datetime->button, - datetime->tooltip_handler_id); - datetime->tooltip_handler_id = 0; - } switch(datetime->layout) { case LAYOUT_DATE: case LAYOUT_TIME: gtk_widget_set_has_tooltip(GTK_WIDGET(datetime->button), TRUE); - datetime->tooltip_handler_id = g_signal_connect(datetime->button, - "query-tooltip", - G_CALLBACK(datetime_query_tooltip), datetime); break; - default: gtk_widget_set_has_tooltip(GTK_WIDGET(datetime->button), FALSE); } @@ -531,16 +585,6 @@ g_free(datetime->time_format); datetime->time_format = g_strdup(time_format); } - - if (datetime_format_has_seconds(datetime->date_format) || - datetime_format_has_seconds(datetime->time_format)) - { - datetime->update_interval = 1000; /* 1 second */ - } - else - { - datetime->update_interval = 60000; /* 1 minute */ - } } /* @@ -658,6 +702,10 @@ /* connect widget signals to functions */ g_signal_connect(datetime->button, "button-press-event", G_CALLBACK(datetime_clicked), datetime); +#if USE_GTK_TOOLTIP_API + g_signal_connect(datetime->button, "query-tooltip", + G_CALLBACK(datetime_query_tooltip), datetime); +#endif } /* @@ -693,8 +741,12 @@ static void datetime_free(XfcePanelPlugin *plugin, t_datetime *datetime) { /* stop timeouts */ - g_source_remove(datetime->timeout_id); - g_source_remove(datetime->tooltip_timeout_id); + if (datetime->timeout_id != 0) + g_source_remove(datetime->timeout_id); +#if USE_GTK_TOOLTIP_API + if (datetime->tooltip_timeout_id != 0) + g_source_remove(datetime->tooltip_timeout_id); +#endif /* destroy widget */ gtk_widget_destroy(datetime->button); diff -u trunk/panel-plugin/datetime.h exp3/panel-plugin/datetime.h --- trunk/panel-plugin/datetime.h 2008-06-08 19:17:04.000000000 -0700 +++ exp3/panel-plugin/datetime.h 2008-06-12 10:13:32.000000000 -0700 @@ -46,11 +46,11 @@ GtkWidget *vbox; GtkWidget *date_label; GtkWidget *time_label; - guint update_interval; /* time between updates in milliseconds */ + guint update_interval; /* time between button updates in milliseconds */ guint timeout_id; #if USE_GTK_TOOLTIP_API + guint tooltip_update_interval; /* time between tooltip updates in milliseconds */ guint tooltip_timeout_id; - gulong tooltip_handler_id; #endif /* settings */ @@ -82,7 +82,7 @@ GtkWidget *cal; } t_datetime; -gboolean +void datetime_update(t_datetime *datetime); gchar *