/* Periodic timer callback. * Also used during initialization and configuration change to do a redraw. */ static gboolean dclock_update_display(DClockPlugin * dc) { /* Determine the current time. */ time_t now; time(&now); struct tm * current_time = localtime(&now); /* Determine the content of the clock label and tooltip. */ char clock_value[64]; char tooltip_value[64]; clock_value[0] = '\0'; if (dc->clock_format != NULL) strftime(clock_value, sizeof(clock_value), dc->clock_format, current_time); tooltip_value[0] = '\0'; if (dc->tooltip_format != NULL) strftime(tooltip_value, sizeof(tooltip_value), dc->tooltip_format, current_time); /* When we write the clock value, it causes the panel to do a full relayout. * Since this function may be called too often while the timing experiment is underway, * we take the trouble to check if the string actually changed first. */ if (( ! dc->icon_only) && ((dc->prev_clock_value == NULL) || (strcmp(dc->prev_clock_value, clock_value) != 0))) { /* Convert "\n" escapes in the user's format string to newline characters. */ char * newlines_converted = NULL; if (strstr(clock_value, "\\n") != NULL) { newlines_converted = g_strdup(clock_value); /* Just to get enough space for the converted result */ char * p; char * q; for (p = clock_value, q = newlines_converted; *p != '\0'; p += 1) { if ((p[0] == '\\') && (p[1] == 'n')) { *q++ = '\n'; p += 1; } else *q++ = *p; } *q = '\0'; } gchar * utf8 = g_locale_to_utf8(((newlines_converted != NULL) ? newlines_converted : clock_value), -1, NULL, NULL, NULL); if (utf8 != NULL) { panel_draw_label_text(dc->plugin->panel, dc->clock_label, utf8, dc->bold, TRUE); g_free(utf8); } g_free(newlines_converted); } /* Determine the content of the tooltip. */ gchar * utf8 = g_locale_to_utf8(tooltip_value, -1, NULL, NULL, NULL); if (utf8 != NULL) { gtk_widget_set_tooltip_text(dc->plugin->pwid, utf8); g_free(utf8); } /* Conduct an experiment to see how often the value changes. * Use this to decide whether we update the value every second or every minute. * We need to account for the possibility that the experiment is being run when we cross a minute boundary. */ if (dc->expiration_interval < ONE_SECOND_INTERVAL) { if (dc->prev_clock_value == NULL) { /* Initiate the experiment. */ dc->prev_clock_value = g_strdup(clock_value); dc->prev_tooltip_value = g_strdup(tooltip_value); } else { if (((dc->icon_only) || (strcmp(dc->prev_clock_value, clock_value) == 0)) && (strcmp(dc->prev_tooltip_value, tooltip_value) == 0)) { dc->experiment_count += 1; if (dc->experiment_count > 3) { /* No change within 3 seconds. Assume change no more often than once per minute. */ dc->expiration_interval = ONE_MINUTE_INTERVAL; g_free(dc->prev_clock_value); g_free(dc->prev_tooltip_value); dc->prev_clock_value = NULL; dc->prev_tooltip_value = NULL; } } else if (dc->expiration_interval == AWAITING_FIRST_CHANGE) { /* We have a change at the beginning of the experiment, but we do not know when the next change might occur. * Continue the experiment for 3 more seconds. */ dc->expiration_interval = AWAITING_SECOND_CHANGE; dc->experiment_count = 0; g_free(dc->prev_clock_value); g_free(dc->prev_tooltip_value); dc->prev_clock_value = g_strdup(clock_value); dc->prev_tooltip_value = g_strdup(tooltip_value); } else { /* We have a second change. End the experiment. */ dc->expiration_interval = ((dc->experiment_count > 3) ? ONE_MINUTE_INTERVAL : ONE_SECOND_INTERVAL); g_free(dc->prev_clock_value); g_free(dc->prev_tooltip_value); dc->prev_clock_value = NULL; dc->prev_tooltip_value = NULL; } } } /* Reset the timer and return. */ dclock_timer_set(dc); return FALSE; }
/* Periodic timer callback. * Also used during initialization and configuration change to do a redraw. */ static gboolean dclock_update_display(DClockPlugin * dc) { /* Determine the current time. */ struct tm * current_time = _get_time_to_display(dc); /* Determine the content of the clock label and tooltip. */ char clock_value[256]; char tooltip_value[256]; clock_value[0] = '\0'; if (dc->clock_format != NULL) strftime(clock_value, sizeof(clock_value), dc->clock_format, current_time); tooltip_value[0] = '\0'; if (dc->tooltip_format != NULL) strftime(tooltip_value, sizeof(tooltip_value), dc->tooltip_format, current_time); /* When we write the clock value, it causes the panel to do a full relayout. * Since this function may be called too often while the timing experiment is underway, * we take the trouble to check if the string actually changed first. */ if ((dc->prev_clock_value == NULL) || (strcmp(dc->prev_clock_value, clock_value) != 0)) { /* Convert "\n" escapes in the user's format string to newline characters. */ char * newlines_converted = NULL; if (strstr(clock_value, "\\n") != NULL) { newlines_converted = g_strdup(clock_value); /* Just to get enough space for the converted result */ char * p; char * q; for (p = clock_value, q = newlines_converted; *p != '\0'; p += 1) { if ((p[0] == '\\') && (p[1] == 'n')) { *q++ = '\n'; p += 1; } else *q++ = *p; } *q = '\0'; } gchar ** segments = g_strsplit( (newlines_converted != NULL) ? newlines_converted : clock_value, "\\t", MAX_LABELS); int i; for (i = 0; i < MAX_LABELS; i++) { if (!segments || !segments[i]) break; if (!dc->clock_labels[i]) { dc->clock_labels[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(dc->clock_labels[i]), 0.5, 0.5); gtk_container_add(GTK_CONTAINER(dc->label_box), dc->clock_labels[i]); gtk_label_set_justify(GTK_LABEL(dc->clock_labels[i]), GTK_JUSTIFY_CENTER); } panel_draw_label_text_with_font( plugin_panel(dc->plugin), dc->clock_labels[i], segments[i], STYLE_CUSTOM_COLOR | STYLE_MARKUP, dc->font); gtk_widget_show(dc->clock_labels[i]); } for (/*nothing*/; i < MAX_LABELS; i++) { if (!dc->clock_labels[i]) break; gtk_widget_hide(dc->clock_labels[i]); } g_strfreev(segments); g_free(newlines_converted); } /* Determine the content of the tooltip. */ gtk_widget_set_tooltip_text(plugin_widget(dc->plugin), tooltip_value); /* Conduct an experiment to see how often the value changes. * Use this to decide whether we update the value every second or every minute. * We need to account for the possibility that the experiment is being run when we cross a minute boundary. */ if (dc->expiration_interval < ONE_SECOND_INTERVAL) { if (dc->prev_clock_value == NULL) { /* Initiate the experiment. */ dc->prev_clock_value = g_strdup(clock_value); dc->prev_tooltip_value = g_strdup(tooltip_value); } else { if ((strcmp(dc->prev_clock_value, clock_value) == 0) && (strcmp(dc->prev_tooltip_value, tooltip_value) == 0)) { dc->experiment_count += 1; if (dc->experiment_count > 3) { /* No change within 3 seconds. Assume change no more often than once per minute. */ dc->expiration_interval = ONE_MINUTE_INTERVAL; g_free(dc->prev_clock_value); g_free(dc->prev_tooltip_value); dc->prev_clock_value = NULL; dc->prev_tooltip_value = NULL; } } else if (dc->expiration_interval == AWAITING_FIRST_CHANGE) { /* We have a change at the beginning of the experiment, but we do not know when the next change might occur. * Continue the experiment for 3 more seconds. */ dc->expiration_interval = AWAITING_SECOND_CHANGE; dc->experiment_count = 0; g_free(dc->prev_clock_value); g_free(dc->prev_tooltip_value); dc->prev_clock_value = g_strdup(clock_value); dc->prev_tooltip_value = g_strdup(tooltip_value); } else { /* We have a second change. End the experiment. */ dc->expiration_interval = ((dc->experiment_count > 3) ? ONE_MINUTE_INTERVAL : ONE_SECOND_INTERVAL); g_free(dc->prev_clock_value); g_free(dc->prev_tooltip_value); dc->prev_clock_value = NULL; dc->prev_tooltip_value = NULL; } } } /* Reset the timer and return. */ dclock_timer_set(dc); return FALSE; }