diff options
author | Thomas White <taw@physics.org> | 2019-12-15 18:20:01 +0100 |
---|---|---|
committer | Thomas White <taw@physics.org> | 2019-12-15 18:20:01 +0100 |
commit | 8f248a7e72045cc3067012f45d101ba825472fea (patch) | |
tree | 986d0c8bec15e51172e526d43202b99942f8719c |
Initial import
-rw-r--r-- | glitchyclock.c | 156 | ||||
-rw-r--r-- | meson.build | 18 |
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) |