#include #include #include #include #include #include #define SECOND_INTERVAL 1000 #define DEFAULT_WIDTH 200 #define DEFAULT_HEIGHT 100 typedef struct { gboolean active; /* whether the selection is active or not */ gdouble x, y; } selection_t; typedef struct { float r; float g; float b; float a; } color_t; static gboolean time_handler (GtkWidget* w) { if (GTK_IS_WIDGET(w)) { gtk_widget_queue_draw (w); return TRUE; } else { _exit(-1); return FALSE; } } gboolean on_key_press (GtkWidget *widget, GdkEventKey *key, gpointer p) { if (key->type == GDK_KEY_PRESS) { switch (key->keyval) { case GDK_Escape : gtk_main_quit (); break; } } return FALSE; } gboolean on_mouse_press (GtkWidget *widget, GdkEventButton *bev, selection_t *sel) { sel->active = TRUE; sel->x = bev->x; sel->y = bev->y; gtk_widget_queue_draw (widget); return TRUE; } gboolean on_mouse_release (GtkWidget *widget, GdkEventButton *bev, selection_t *sel) { sel->active = FALSE; sel->x = 0; sel->y = 0; gtk_widget_queue_draw (widget); return TRUE; } gboolean on_mouse_motion (GtkWidget *widget, GdkEventButton *bev, selection_t *sel) { sel->x = bev->x; sel->y = bev->y; gtk_widget_queue_draw (widget); return TRUE; } static void paint_dot (cairo_t *cr, selection_t *sel) { if (!sel->active) return; cairo_save (cr); cairo_arc (cr, sel->x, sel->y, 30., 0., 2 * M_PI); cairo_set_source_rgba (cr, 0, 0, 0, 0.2); cairo_fill_preserve (cr); cairo_set_source_rgba (cr, 0, 0, 0, 0.5); cairo_stroke (cr); cairo_restore (cr); } void paint_rounded_box (cairo_t *cr, float x, float y, float w, float h, color_t *o, color_t *f, float c) { gint t, i; cairo_save (cr); cairo_translate (cr, x, y); if (f) cairo_set_source_rgba (cr, f->r, f->g, f->b, f->a); cairo_move_to (cr, - w/2, - h/2 + c); for ( i = 0; i < 4; i++ ) { cairo_translate (cr, -w/2.0, -h/2.0); cairo_curve_to (cr, 0.0, c, 0.0, 0.0, c, 0.0); cairo_line_to (cr, w - c, 0.0); cairo_translate (cr, w/2.0, h/2.0); cairo_rotate (cr, M_PI/2.0); t = w; w = h; h = t; } if (f) cairo_fill_preserve (cr); cairo_set_source_rgba (cr, o->r, o->g, o->b, o->a); cairo_stroke (cr); cairo_restore (cr); } void paint_rect (cairo_t *cr, float x, float y, float w, float h, color_t *o, color_t *f) { cairo_save (cr); cairo_translate (cr, x, y); if (f) cairo_set_source_rgba (cr, f->r, f->g, f->b, f->a); cairo_rectangle (cr, -w/2, -h/2, w, h); if (f) cairo_fill_preserve (cr); cairo_set_source_rgba (cr, o->r, o->g, o->b, o->a); cairo_stroke (cr); cairo_restore (cr); } void paint_clock_dot (cairo_t *cr, float x, float y, float w, float h, color_t *c) { color_t back_o = { 0.0f, 0.0f, 0.0f, 1.0f }; /* paint_rounded_box (cr, x, y, w, h, &back_o, c, 5);*/ paint_rect (cr, x, y, w, h, &back_o, c); } static void paint (GtkWidget *widget, GdkEventExpose *eev, selection_t *sel) { gint width, height; cairo_t *cr; gint i, j; time_t now; struct tm *tm; int timet[3]; color_t color[] = {{ 1.0f, 0.0f, 0.0f, 0.6f }, { 0.0f, 1.0f, 0.0f, 0.6f }, { 0.0f, 0.0f, 1.0f, 0.6f }}; now = time(NULL); tm = localtime(&now); timet[0] = tm->tm_hour; timet[1] = tm->tm_min; timet[2] = tm->tm_sec; width = widget->allocation.width; height = widget->allocation.height; cr = gdk_cairo_create (widget->window); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 0.4f); cairo_paint (cr); for (i = 0; i < 3; i++) { for (j = 0; j < 6; j++) { paint_clock_dot (cr, (width/7)*(6-j) , (height/4)*(i+1), (width/8), (height/5), (((timet[i])>>j)&0x1)?&color[i]:NULL); } } paint_dot (cr, sel); cairo_destroy (cr); } static void install_colormap (GtkWidget *w) { GdkScreen* screen = gtk_widget_get_screen (w); GdkColormap* colormap = gdk_screen_get_rgba_colormap (screen); if (!colormap) colormap = gdk_screen_get_rgb_colormap (screen); gtk_widget_set_colormap (w, colormap); } gint main (gint argc, gchar **argv) { GtkWidget *window; selection_t sel = {FALSE, 0, 0,}; gtk_init(&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_stick (GTK_WINDOW (window)); // gtk_window_set_keep_below (GTK_WINDOW (window), TRUE); gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE); gtk_window_set_skip_pager_hint (GTK_WINDOW (window), TRUE); // gtk_window_set_accept_focus (GTK_WINDOW (window), FALSE); gtk_window_set_decorated (GTK_WINDOW (window), TRUE); gtk_window_set_resizable (GTK_WINDOW (window), TRUE); gtk_widget_set_app_paintable (window, TRUE); gtk_window_set_default_size (GTK_WINDOW (window), DEFAULT_WIDTH, DEFAULT_HEIGHT); install_colormap(window); gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK); g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (paint), &sel); g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK (on_key_press), NULL); /* connect our rubber banding callbacks, like the paint callback * we pass the selection as userdata */ g_signal_connect (G_OBJECT (window), "button_press_event", G_CALLBACK (on_mouse_press), &sel); g_signal_connect (G_OBJECT (window), "button_release_event", G_CALLBACK (on_mouse_release), &sel); g_signal_connect (G_OBJECT (window), "motion_notify_event", G_CALLBACK (on_mouse_motion), &sel); g_timeout_add (SECOND_INTERVAL/9, (GtkFunction) time_handler, window); gtk_widget_show_all (window); gtk_main (); return 0; }