[PATCH] example for gtk-demo demonstrating offscreen-rendered widgets with reflection-effect
- From: Mirco Müller <macslow bangang de>
- To: gtk-devel-list <gtk-devel-list gnome org>
- Subject: [PATCH] example for gtk-demo demonstrating offscreen-rendered widgets with reflection-effect
- Date: Sat, 22 Dec 2007 21:22:25 +0100
Greetings gtk+-crowd!
Here is a patch for gtk-demo adding an example showing off redirected
widget drawing with a reflection effect. The patch applies to gtk+
r19219.
Screenshot:
http://macslow.thepimp.net/shots/offscreen-widgets-demo.png
Best regards...
Mirco "MacSlow" Müller
diff -Naur gtk-demo.orig/composited_window.c gtk-demo/composited_window.c
--- gtk-demo.orig/composited_window.c 1970-01-01 01:00:00.000000000 +0100
+++ gtk-demo/composited_window.c 2007-12-22 21:04:14.000000000 +0100
@@ -0,0 +1,222 @@
+/* Composited Window
+ *
+ * Offscreen rendered widgets are used to achieve a reflection effect. Only
+ * works under X11!
+ */
+
+#include <gtk/gtk.h>
+
+#ifdef GDK_WINDOWING_X11
+
+static gboolean
+window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkWidget *child;
+ cairo_t *cr;
+ gdouble color[3];
+ cairo_matrix_t matrix;
+ cairo_pattern_t *mask;
+ GtkStyle *style;
+
+ /* get our child... here the event-box */
+ child = gtk_bin_get_child (GTK_BIN (widget));
+
+ /* create a cairo context to draw to the window */
+ cr = gdk_cairo_create (widget->window);
+
+ /* redirect output for double-buffering */
+ cairo_push_group (cr);
+
+ /* write/paint over everything else */
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+ /* set clip-region to windows dimensions */
+ cairo_rectangle (cr,
+ (gdouble) widget->allocation.x,
+ (gdouble) widget->allocation.y,
+ (gdouble) widget->allocation.width,
+ (gdouble) widget->allocation.height);
+ cairo_clip (cr);
+
+ /* get theme background-color and clear/paint the context with it */
+ style = gtk_widget_get_style (widget);
+ color[0] = (gdouble) style->bg[GTK_STATE_NORMAL].red;
+ color[1] = (gdouble) style->bg[GTK_STATE_NORMAL].green;
+ color[2] = (gdouble) style->bg[GTK_STATE_NORMAL].blue;
+ color[0] /= (gdouble) 0xFFFF;
+ color[1] /= (gdouble) 0xFFFF;
+ color[2] /= (gdouble) 0xFFFF;
+ cairo_set_source_rgb (cr, color[0], color[1], color[2]);
+ cairo_paint (cr);
+
+ /* obtain the the source data... here the composited event-box */
+ cairo_save (cr);
+ gdk_cairo_set_source_pixmap (cr,
+ child->window,
+ child->allocation.x,
+ child->allocation.y);
+
+ /* draw it at its original position */
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ /* setup transformation-matrix to mirror the source and move it down */
+ cairo_save (cr);
+ cairo_matrix_init_scale (&matrix, 1.0f, -1.0f);
+ cairo_matrix_translate (&matrix, 0.0f, -95.0f);
+ cairo_transform (cr, &matrix);
+
+ /* get the source again */
+ gdk_cairo_set_source_pixmap (cr,
+ child->window,
+ child->allocation.x,
+ child->allocation.y);
+
+ /* create linear gradient as mask-pattern to fade out the source */
+ mask = cairo_pattern_create_linear (0.0f, 0.0f, 0.0f, (gdouble) 68);
+ cairo_pattern_add_color_stop_rgba (mask, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+ cairo_pattern_add_color_stop_rgba (mask, 0.25f, 0.0f, 0.0f, 0.0f, 0.01f);
+ cairo_pattern_add_color_stop_rgba (mask, 0.5f, 0.0f, 0.0f, 0.0f, 0.125f);
+ cairo_pattern_add_color_stop_rgba (mask, 0.75f, 0.0f, 0.0f, 0.0f, 0.5f);
+ cairo_pattern_add_color_stop_rgba (mask, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
+
+ /* apply and draw the current source with the mask-pattern */
+ cairo_mask (cr, mask);
+
+ /* get rid of the mask-pattern again */
+ cairo_pattern_destroy (mask);
+ cairo_restore (cr);
+
+ /* draw the buffered contents */
+ cairo_pop_group_to_source (cr);
+ cairo_paint (cr);
+
+ /* we're done */
+ cairo_destroy (cr);
+
+ return TRUE;
+}
+
+static gboolean
+transparent_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ cairo_t *cr;
+
+ cr = gdk_cairo_create (widget->window);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ gdk_cairo_region (cr, event->region);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+GtkWidget *
+do_composited_window (GtkWidget *do_widget)
+{
+ static GtkWidget *window = NULL;
+ GtkWidget *alignment;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *event;
+ GtkWidget *backbutton;
+ GtkWidget *applybutton;
+ GtkWidget *entry;
+ GdkScreen *screen;
+ GdkColormap *colormap;
+
+ if (!window)
+ {
+ /* create the widgets */
+ alignment = gtk_alignment_new (0.5f, 0.0f, 1.0f, 0.0f);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 34, 0, 0);
+ vbox = gtk_vbox_new (FALSE, 6);
+ hbox = gtk_hbox_new (FALSE, 6);
+ backbutton = gtk_button_new ();
+ gtk_container_add (GTK_CONTAINER (backbutton),
+ gtk_image_new_from_stock (GTK_STOCK_GO_BACK, 4));
+ entry = gtk_entry_new ();
+ gtk_widget_set_size_request (entry, -1, 34);
+ applybutton = gtk_button_new ();
+ gtk_container_add (GTK_CONTAINER (applybutton),
+ gtk_image_new_from_stock (GTK_STOCK_APPLY, 4));
+ event = gtk_event_box_new ();
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ /* if we don't do this, the reflection gets not updated at the right
+ * time */
+ gtk_widget_set_double_buffered (window, FALSE);
+
+ /* set the colormap for the event box... must be done before the event
+ * box is realised. */
+ screen = gtk_widget_get_screen (event);
+ colormap = gdk_screen_get_rgba_colormap (screen);
+ gtk_widget_set_colormap (event, colormap);
+
+ /* set title for the window */
+ gtk_window_set_title (GTK_WINDOW (window), "gtk+ offscreen widgets");
+
+ /* set our event box to have a fully transparent background
+ * drawn on it... currently there is no way to simply tell GTK+
+ * that "transparency" is the background colour for a widget */
+ gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
+ g_signal_connect (event,
+ "expose-event",
+ G_CALLBACK (transparent_expose),
+ NULL);
+
+ /* stuff it all together */
+ gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+ gtk_container_add (GTK_CONTAINER (window), event);
+ gtk_container_add (GTK_CONTAINER (event), alignment);
+ gtk_container_add (GTK_CONTAINER (alignment), hbox);
+ gtk_box_pack_start (GTK_BOX (hbox), backbutton, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), applybutton, FALSE, FALSE, 0);
+
+ /* realize everything */
+ gtk_widget_realize (window);
+
+ /* connect the windows close-button */
+ g_signal_connect (window,
+ "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &window);
+
+ /* connect the compositing handler */
+ g_signal_connect (window,
+ "expose-event",
+ G_CALLBACK (window_expose_event),
+ NULL);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ {
+ gtk_widget_show_all (window);
+
+ /* set the event box GdkWindow to be composited.
+ * obviously must be performed after event box is realised.
+ */
+ gdk_window_set_composited (event->window, TRUE);
+ }
+ else
+ {
+ gtk_widget_destroy (window);
+ window = NULL;
+ }
+
+ return window;
+}
+
+#elif /* GDK_WINDOWING_X11 */
+
+GtkWidget *
+do_composited_window (GtkWidget *do_widget)
+{
+ return NULL;
+}
+
+#endif /* GDK_WINDOWING_X11 */
+
diff -Naur gtk-demo.orig/Makefile.am gtk-demo/Makefile.am
--- gtk-demo.orig/Makefile.am 2007-12-22 20:36:58.000000000 +0100
+++ gtk-demo/Makefile.am 2007-12-22 21:04:14.000000000 +0100
@@ -14,6 +14,7 @@
clipboard.c \
colorsel.c \
combobox.c \
+ composited_window.c \
dialog.c \
drawingarea.c \
editable_cells.c \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]