[PATCH v3] desktop-shell: Configurable clock format, fix accuracy

Martin Minarik minarik11 at student.fiit.stuba.sk
Sun Jun 24 06:46:55 PDT 2012


Add weston.ini section to allow customizing the
format of the displayed time. The redraw interval
is based on whether the required format
contains a second entries (%S %s %T).
Synchronize redrawing the clock exactly with system time.
Get time from gettimeofday(), instead of time().

Avoid redrawing the clock with zero size allocation, by starting
the clock timer after successful allocation in panel_resize_handler.
---
 clients/desktop-shell.c |   86 +++++++++++++++++++++++++++++++++++++++++------
 weston.ini              |    3 ++
 2 files changed, 78 insertions(+), 11 deletions(-)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 6c73a5c..59cebca 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -97,6 +97,9 @@ struct panel_clock {
 	struct panel *panel;
 	struct task clock_task;
 	int clock_fd;
+	int run;
+	char *time_format;
+	unsigned int interval;
 };
 
 struct unlock_dialog {
@@ -114,7 +117,9 @@ static uint32_t key_panel_color = 0xaa000000;
 static uint32_t key_background_color = 0xff002244;
 static char *key_launcher_icon;
 static char *key_launcher_path;
+static char *key_clock_format = NULL;
 static void launcher_section_done(void *data);
+static void clock_section_done(void *data);
 static int key_locking = 1;
 
 static const struct config_key shell_config_keys[] = {
@@ -130,12 +135,19 @@ static const struct config_key launcher_config_keys[] = {
 	{ "path", CONFIG_KEY_STRING, &key_launcher_path },
 };
 
+static const struct config_key clock_config_keys[] = {
+	{ "format", CONFIG_KEY_STRING, &key_clock_format },
+};
+
 static const struct config_section config_sections[] = {
 	{ "shell",
 	  shell_config_keys, ARRAY_LENGTH(shell_config_keys) },
 	{ "launcher",
 	  launcher_config_keys, ARRAY_LENGTH(launcher_config_keys),
-	  launcher_section_done }
+	  launcher_section_done },
+	{ "clock",
+	  clock_config_keys, ARRAY_LENGTH(clock_config_keys),
+	  clock_section_done }
 };
 
 static void
@@ -313,13 +325,15 @@ panel_clock_redraw_handler(struct widget *widget, void *data)
 	struct rectangle allocation;
 	cairo_text_extents_t extents;
 	cairo_font_extents_t font_extents;
-	time_t rawtime;
 	struct tm * timeinfo;
+	struct timeval tv;
 	char string[128];
 
-	time(&rawtime);
-	timeinfo = localtime(&rawtime);
-	strftime(string, sizeof string, "%a %b %d, %I:%M %p", timeinfo);
+	gettimeofday(&tv, NULL);
+
+	timeinfo = localtime(&tv.tv_sec);
+
+	strftime(string, sizeof string, clock->time_format, timeinfo);
 
 	widget_get_allocation(widget, &allocation);
 	if (allocation.width == 0)
@@ -349,11 +363,11 @@ clock_timer_reset(struct panel_clock *clock)
 {
 	struct itimerspec its;
 
-	its.it_interval.tv_sec = 60;
+	its.it_interval.tv_sec = clock->run ? clock->interval : 0;
 	its.it_interval.tv_nsec = 0;
-	its.it_value.tv_sec = 60;
+	its.it_value.tv_sec =  clock->run ? clock->interval : 0;
 	its.it_value.tv_nsec = 0;
-	if (timerfd_settime(clock->clock_fd, 0, &its, NULL) < 0) {
+	if (timerfd_settime(clock->clock_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
 		fprintf(stderr, "could not set timerfd\n: %m");
 		return -1;
 	}
@@ -362,12 +376,28 @@ clock_timer_reset(struct panel_clock *clock)
 }
 
 static void
+clock_start(struct panel_clock *clock)
+{
+	clock->run = 1;
+	clock_timer_reset(clock);
+}
+
+static void
+clock_stop(struct panel_clock *clock)
+{
+	clock->run = 0;
+	clock_timer_reset(clock);
+}
+
+static char *clock_default_time_format = "%a %b %d, %I:%M:%S %p";
+
+static void
 panel_add_clock(struct panel *panel)
 {
 	struct panel_clock *clock;
 	int timerfd;
 
-	timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+	timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
 	if (timerfd < 0) {
 		fprintf(stderr, "could not create timerfd\n: %m");
 		return;
@@ -378,11 +408,14 @@ panel_add_clock(struct panel *panel)
 	clock->panel = panel;
 	panel->clock = clock;
 	clock->clock_fd = timerfd;
+	clock->time_format = clock_default_time_format;
+	clock->interval = 60;
+	clock->run = 0;
 
 	clock->clock_task.run = clock_func;
 	display_watch_fd(window_get_display(panel->window), clock->clock_fd,
 			 EPOLLIN, &clock->clock_task);
-	clock_timer_reset(clock);
+	clock_stop(clock);
 
 	clock->widget = widget_add_widget(panel->widget, clock);
 	widget_set_redraw_handler(clock->widget, panel_clock_redraw_handler);
@@ -420,9 +453,11 @@ panel_resize_handler(struct widget *widget,
 	h=20;
 	w=170;
 
-	if (panel->clock)
+	if (panel->clock) {
 		widget_set_allocation(panel->clock->widget,
 				      width - w - 8, y - h / 2, w + 1, h + 1);
+		clock_start(panel->clock);
+	}
 }
 
 static void
@@ -846,6 +881,35 @@ launcher_section_done(void *data)
 }
 
 static void
+clock_section_done(void *data)
+{
+	struct desktop *desktop = data;
+	struct output *output;
+
+	char * new_format = malloc ((strlen(key_clock_format) + 2) * sizeof(char));
+	if (new_format == NULL)
+		return;
+	sprintf(new_format, "%s", key_clock_format);
+
+	wl_list_for_each(output, &desktop->outputs, link) {
+		struct panel_clock *clock = output->panel->clock;
+		clock->time_format = new_format;
+
+#define CONTAINS(X) (strstr(new_format, X) != NULL)
+		if (CONTAINS("%S") || CONTAINS("%s") || CONTAINS("%T"))
+#undef CONTAINS
+			clock->interval = 1;
+		else
+			clock->interval = 60;
+
+		clock_timer_reset(clock);
+	}
+
+	free(key_clock_format);
+	key_clock_format = NULL;
+}
+
+static void
 add_default_launcher(struct desktop *desktop)
 {
 	struct output *output;
diff --git a/weston.ini b/weston.ini
index 7693253..a77ea80 100644
--- a/weston.ini
+++ b/weston.ini
@@ -27,6 +27,9 @@ path=/usr/bin/google-chrome
 icon=/usr/share/icons/gnome/24x24/apps/arts.png
 path=./clients/flower
 
+[clock]
+#format=%a %b %d, %I:%M %p
+
 [screensaver]
 #path=./clients/wscreensaver
 duration=600
-- 
1.7.5.4



More information about the wayland-devel mailing list