/**
 * thp's neat Cheese-ish photo flash simulator
 * Proposed fix for: http://bugzilla.gnome.org/show_bug.cgi?id=526214
 *
 * This creates a white, fullscreen gtk window that is transparent and
 * will quickly have its opacity go up and then down again, yielding a
 * similiar effect like that of a well-known webcam utility ;)
 *
 * Caveats:
 * Requires a compositing manager (like Compiz or Metacity w/ compositing)
 *
 * Compile with:
 * gcc -o flasher flasher.c `pkg-config --libs --cflags gtk+-2.0`
 *
 * Copyright (c) 2008-05-22 Thomas Perl <thpinfo.com>
 * License: GPLv2 or later (same as the Cheese package)
 **/

#include <gtk/gtk.h>



/* timestep for opacity changes */
#define TIMEOUT_MS 35

/* starting, stepping (via factor multiplication) and stopping to go up */
#define GO_UP_START_VALUE 0.2
#define GO_UP_FACTOR 1.6
#define GO_UP_CHANGE_DIRECTION 0.99

/* start to go down with the start value (has to be <1.0 to work) to quit */
#define GO_DOWN_START_VALUE 0.999
#define GO_DOWN_QUIT_VALUE 0.01



/**
 * This function is used to make the window completely
 * white for total flash awesomeness!
 **/
gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
    cairo_t *cr;

    cr = gdk_cairo_create(widget->window);
    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_rectangle(cr,
            event->area.x, event->area.y,
            event->area.width, event->area.height);
    cairo_fill(cr);
    cairo_destroy(cr);

    return TRUE;
}


/**
 * The timeout callback to change the window opacity
 **/
gboolean opacity_change(gpointer data)
{
    /**
     * First, we go up (increase opacity), then
     * direction_up is TRUE. After that, we go
     * down again (decreate opacity) with FALSE.
     **/
    static gboolean direction_up = TRUE;

    GtkWindow* w = (GtkWindow*)data;
    gdouble opacity = gtk_window_get_opacity(w);

    if (direction_up == TRUE) {
        if (opacity >= GO_UP_CHANGE_DIRECTION) {
            /* we start to go down here */
            direction_up = FALSE;
            gtk_window_set_opacity(w, GO_DOWN_START_VALUE);
        } else {
            gtk_window_set_opacity(w, opacity*GO_UP_FACTOR);
        }
    } else {
        /* the opacity is squared, which makes it decrease */
        gtk_window_set_opacity(w, opacity*opacity);
    }

    if (opacity <= GO_DOWN_QUIT_VALUE) {
        /* the flasher has finished when we reach the quit value */
        gtk_main_quit();
    }

    return TRUE;
}

int main(int argc, char **argv)
{
    GtkWidget *w;
    GdkColormap *colormap;
    GdkScreen *screen;

    gtk_init(&argc, &argv);

    w = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    screen = gtk_widget_get_screen(w);
    colormap = gdk_screen_get_rgba_colormap (screen);
    if (!colormap)
        colormap = gdk_screen_get_rgb_colormap (screen);
    gtk_widget_set_colormap (w, colormap);

    /* make it so it doesn't look like a window on the desktop (+fullscreen) */
    gtk_window_set_decorated(GTK_WINDOW(w), FALSE);  
    gtk_window_set_skip_taskbar_hint(GTK_WINDOW(w), TRUE);
    gtk_window_set_skip_pager_hint(GTK_WINDOW(w), TRUE);
    gtk_window_fullscreen(GTK_WINDOW(w));

    g_signal_connect(w, "expose-event", G_CALLBACK(expose_event), NULL);
    g_signal_connect(w, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    gtk_window_set_opacity(GTK_WINDOW(w), GO_UP_START_VALUE);
    g_timeout_add(TIMEOUT_MS, opacity_change, (gpointer)w);

    gtk_widget_show_all(GTK_WIDGET(w));
    gtk_main();

    return 0;
}

