summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2019-12-15 18:20:01 +0100
committerThomas White <taw@physics.org>2019-12-15 18:20:01 +0100
commit8f248a7e72045cc3067012f45d101ba825472fea (patch)
tree986d0c8bec15e51172e526d43202b99942f8719c
Initial import
-rw-r--r--glitchyclock.c156
-rw-r--r--meson.build18
2 files changed, 174 insertions, 0 deletions
diff --git a/glitchyclock.c b/glitchyclock.c
new file mode 100644
index 0000000..ec27cd6
--- /dev/null
+++ b/glitchyclock.c
@@ -0,0 +1,156 @@
+#include <gtk/gtk.h>
+
+struct glitchyclock
+{
+ GtkWidget *da;
+ PangoFontDescription *fontdesc;
+ int nglitch;
+ time_t glitch_base;
+};
+
+
+const int glitch_times[] = {
+ 7, 15,
+ 23, 58,
+ -1, -1
+};
+
+
+static time_t get_monotonic_seconds()
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ return tp.tv_sec;
+}
+
+
+static void do_glitch(struct glitchyclock *gc)
+{
+ if ( glitch_times[2*(gc->nglitch+1)] == -1 ) return;
+ gc->nglitch++;
+ gc->glitch_base = get_monotonic_seconds();
+}
+
+
+static gboolean draw_sig(GtkWidget *widget, cairo_t *cr, struct glitchyclock *gc)
+{
+ int w, h;
+ int lw, lh;
+ double sf;
+ PangoLayout *layout;
+ const double screen_w_frac = 0.4;
+ int glitch_hours, glitch_minutes;
+ char timestr[64];
+ int seconds;
+
+ w = gtk_widget_get_allocated_width(widget);
+ h = gtk_widget_get_allocated_height(widget);
+
+ /* Overall background */
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_paint(cr);
+
+ layout = pango_layout_new(gtk_widget_get_pango_context(widget));
+ pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+ pango_layout_set_font_description(layout, gc->fontdesc);
+
+ glitch_hours = glitch_times[gc->nglitch*2];
+ glitch_minutes = glitch_times[gc->nglitch*2+1];
+ seconds = get_monotonic_seconds() - gc->glitch_base;
+
+ if ( seconds < 4 ) {
+ strcpy(timestr, "rK:S8");
+ } else {
+ int hours, minutes;
+ hours = (seconds/3600 + glitch_hours) % 24;
+ minutes = (seconds/60 + glitch_minutes) % 60;
+ snprintf(timestr, 63, "%02i:%02i", hours, minutes);
+ }
+ pango_layout_set_text(layout, timestr, -1);
+
+ pango_cairo_update_layout(cr, layout);
+ pango_layout_get_size(layout, &lw, &lh);
+
+ sf = (double)PANGO_SCALE*screen_w_frac*w/lw;
+ cairo_scale(cr, sf, sf);
+ pango_cairo_update_layout(cr, layout);
+
+ pango_layout_get_size(layout, &lw, &lh);
+ lw /= PANGO_SCALE; lh /= PANGO_SCALE;
+ w /= sf; h /= sf;
+ cairo_translate(cr, (w-lw)/2.0, h-lh);
+ pango_cairo_update_layout(cr, layout);
+
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+ pango_cairo_show_layout(cr, layout);
+
+ return FALSE;
+}
+
+
+static gboolean redraw_cb(gpointer data)
+{
+ gint w, h;
+ struct glitchyclock *gc = data;
+ w = gtk_widget_get_allocated_width(GTK_WIDGET(gc->da));
+ h = gtk_widget_get_allocated_height(GTK_WIDGET(gc->da));
+ gtk_widget_queue_draw_area(GTK_WIDGET(gc->da), 0, 0, w, h);
+ return G_SOURCE_CONTINUE;
+}
+
+
+static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, struct glitchyclock *gc)
+{
+ if ( event->keyval == GDK_KEY_KP_Enter ) {
+ do_glitch(gc);
+ redraw_cb(gc);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static gint realise_sig(GtkWidget *da, struct glitchyclock *gc)
+{
+ GdkWindow *win = gtk_widget_get_window(da);
+
+ /* Keyboard and input method stuff */
+ gdk_window_set_accept_focus(win, TRUE);
+ g_signal_connect(G_OBJECT(da), "key-press-event", G_CALLBACK(key_press_sig), gc);
+
+ gc->fontdesc = pango_font_description_from_string("DSEG7 Modern Bold 16");
+
+ return FALSE;
+}
+
+
+int main(int argc, char *argv[])
+{
+ struct glitchyclock gc;
+ GtkWidget *mainwindow;
+
+ gc.nglitch = 0;
+ gc.glitch_base = get_monotonic_seconds();
+ gtk_init(&argc, &argv);
+
+ mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_fullscreen(GTK_WINDOW(mainwindow));
+ g_signal_connect_swapped(G_OBJECT(mainwindow), "destroy", gtk_main_quit, NULL);
+
+ gc.da = gtk_drawing_area_new();
+ gtk_container_add(GTK_CONTAINER(mainwindow), GTK_WIDGET(gc.da));
+ gtk_widget_set_can_focus(GTK_WIDGET(gc.da), TRUE);
+ gtk_widget_add_events(gc.da, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
+ g_signal_connect(G_OBJECT(gc.da), "draw", G_CALLBACK(draw_sig), &gc);
+ g_signal_connect(G_OBJECT(gc.da), "realize", G_CALLBACK(realise_sig), &gc);
+
+ gtk_widget_grab_focus(GTK_WIDGET(gc.da));
+ gtk_widget_show_all(mainwindow);
+
+ g_timeout_add(1000, redraw_cb, &gc);
+
+ gtk_main();
+
+ return 0;
+}
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..97fd6cd
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,18 @@
+# Meson file for GlitchyClock
+project('glitchyclock', 'c',
+ version : '0.1.0',
+ license : 'GPL3+',
+ default_options : ['buildtype=debugoptimized'])
+
+# Dependencies
+cc = meson.get_compiler('c')
+mdep = cc.find_library('m', required : false)
+gtk_dep = dependency('gtk+-3.0', required : true)
+cairo_dep = dependency('cairo', required : true)
+
+# Main program
+executable('glitchyclock',
+ ['glitchyclock.c',
+ ],
+ dependencies : [gtk_dep, mdep],
+ install : true)