diff options
author | Jon TURNEY <jon.turney@dronecode.org.uk> | 2012-11-02 21:01:31 +0000 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2012-11-02 21:01:37 +0000 |
commit | 21a4ce2d6c607ad6800fa4391fd1f63a02500e9b (patch) | |
tree | f98dab52d13d5e6e331aa98f6cdee3332aadcf09 |
alphademo
from http://plan99.net/~mike/files/alphademo.c
-rw-r--r-- | alphademo.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/alphademo.c b/alphademo.c new file mode 100644 index 0000000..5e19429 --- /dev/null +++ b/alphademo.c @@ -0,0 +1,127 @@ +// gcc -o alphademo alphademo.c `pkg-config --cflags --libs gtk+-2.0` + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <cairo.h> + +/* + * This program shows you how to create semi-transparent windows, + * without any of the historical screenshot hacks. It requires + * a modern system, with a compositing manager. I use xcompmgr + * and the nvidia drivers with RenderAccel, and it works well. + * + * I'll take you through each step as we go. Minimal GTK+ knowledge is + * assumed. + */ + +static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer user_data); +static gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data); +static void clicked(GtkWindow *win, GdkEventButton *event, gpointer user_data); + +int main(int argc, char **argv) +{ + /* boilerplate initialization code */ + gtk_init(&argc, &argv); + + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "Alpha Demo"); + g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL); + + + /* Tell GTK+ that we want to draw the windows background ourself. + * If we don't do this then GTK+ will clear the window to the + * opaque theme default color, which isn't what we want. + */ + gtk_widget_set_app_paintable(window, TRUE); + + /* We need to handle two events ourself: "expose-event" and "screen-changed". + * + * The X server sends us an expose event when the window becomes + * visible on screen. It means we need to draw the contents. On a + * composited desktop expose is normally only sent when the window + * is put on the screen. On a non-composited desktop it can be + * sent whenever the window is uncovered by another. + * + * The screen-changed event means the display to which we are + * drawing changed. GTK+ supports migration of running + * applications between X servers, which might not support the + * same features, so we need to check each time. + */ + + g_signal_connect(G_OBJECT(window), "expose-event", G_CALLBACK(expose), NULL); + g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(screen_changed), NULL); + + /* toggle title bar on click - we add the mask to tell X we are interested in this event */ + gtk_window_set_decorated(GTK_WINDOW(window), FALSE); + gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); + g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(clicked), NULL); + + /* initialize for the current display */ + screen_changed(window, NULL, NULL); + + /* Run the program */ + gtk_widget_show_all(window); + gtk_main(); + + return 0; +} + + +/* Only some X servers support alpha channels. Always have a fallback */ +gboolean supports_alpha = FALSE; + +static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer userdata) +{ + /* To check if the display supports alpha channels, get the colormap */ + GdkScreen *screen = gtk_widget_get_screen(widget); + GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen); + + if (!colormap) + { + printf("Your screen does not support alpha channels!\n"); + colormap = gdk_screen_get_rgb_colormap(screen); + supports_alpha = FALSE; + } + else + { + printf("Your screen supports alpha channels!\n"); + supports_alpha = TRUE; + } + + /* Now we have a colormap appropriate for the screen, use it */ + gtk_widget_set_colormap(widget, colormap); +} + +/* This is called when we need to draw the windows contents */ +static gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer userdata) +{ + cairo_t *cr = gdk_cairo_create(widget->window); + + if (supports_alpha) + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */ + else + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */ + + /* draw the background */ + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + /* draw a circle */ + int width, height; + gtk_window_get_size(GTK_WINDOW(widget), &width, &height); + + cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.6); + cairo_arc(cr, width / 2, height / 2, (width < height ? width : height) / 2 - 8 , 0, 2 * 3.14); + cairo_fill(cr); + cairo_stroke(cr); + + cairo_destroy(cr); + return FALSE; +} + +static void clicked(GtkWindow *win, GdkEventButton *event, gpointer user_data) +{ + /* toggle window manager frames */ + gtk_window_set_decorated(win, !gtk_window_get_decorated(win)); +} + |