summaryrefslogtreecommitdiff
path: root/tests/testgtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/testgtk.c')
-rw-r--r--tests/testgtk.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 82894e9706..44eb4fcc50 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -421,6 +421,146 @@ create_alpha_window (GtkWidget *widget)
}
/*
+ * Composited non-toplevel window
+ */
+
+/* The expose event handler for the event box.
+ *
+ * This function simply draws a transparency onto a widget on the area
+ * for which it receives expose events. This is intended to give the
+ * event box a "transparent" background.
+ *
+ * In order for this to work properly, the widget must have an RGBA
+ * colourmap. The widget should also be set as app-paintable since it
+ * doesn't make sense for GTK to draw a background if we are drawing it
+ * (and because GTK might actually replace our transparency with its
+ * default background colour).
+ */
+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;
+}
+
+/* The expose event handler for the window.
+ *
+ * This function performs the actual compositing of the event box onto
+ * the already-existing background of the window at 50% normal opacity.
+ *
+ * In this case we do not want app-paintable to be set on the widget
+ * since we want it to draw its own (red) background. Because of this,
+ * however, we must ensure that we use g_signal_register_after so that
+ * this handler is called after the red has been drawn. If it was
+ * called before then GTK would just blindly paint over our work.
+ */
+static gboolean
+window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GdkRegion *region;
+ GtkWidget *child;
+ cairo_t *cr;
+
+ /* get our child (in this case, 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);
+
+ /* the source data is the (composited) event box */
+ gdk_cairo_set_source_pixmap (cr, child->window,
+ child->allocation.x,
+ child->allocation.y);
+
+ /* draw no more than our expose event intersects our child */
+ region = gdk_region_rectangle (&child->allocation);
+ gdk_region_intersect (region, event->region);
+ gdk_cairo_region (cr, region);
+ cairo_clip (cr);
+
+ /* composite, with a 50% opacity */
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_paint_with_alpha (cr, 0.5);
+
+ /* we're done */
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+void
+create_composited_window (GtkWidget *widget)
+{
+ static GtkWidget *window;
+
+ if (!window)
+ {
+ GtkWidget *event, *button;
+ GdkScreen *screen;
+ GdkColormap *rgba;
+ GdkColor red;
+
+ /* make the widgets */
+ button = gtk_button_new_with_label ("A Button");
+ event = gtk_event_box_new ();
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ /* put a red background on the window */
+ gdk_color_parse ("red", &red);
+ gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &red);
+
+ /* set the colourmap for the event box.
+ * must be done before the event box is realised.
+ */
+ screen = gtk_widget_get_screen (event);
+ rgba = gdk_screen_get_rgba_colormap (screen);
+ gtk_widget_set_colormap (event, rgba);
+
+ /* 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);
+
+ /* put them inside one another */
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+ gtk_container_add (GTK_CONTAINER (window), event);
+ gtk_container_add (GTK_CONTAINER (event), button);
+
+ /* realise and show everything */
+ gtk_widget_realize (button);
+
+ /* set the event box GdkWindow to be composited.
+ * obviously must be performed after event box is realised.
+ */
+ gdk_window_set_composited (event->window, TRUE);
+
+ /* set up the compositing handler.
+ * note that we do _after so that the normal (red) background is drawn
+ * by gtk before our compositing occurs.
+ */
+ g_signal_connect_after (window, "expose-event",
+ G_CALLBACK (window_expose_event), NULL);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show_all (window);
+ else
+ gtk_widget_destroy (window);
+}
+
+/*
* Big windows and guffaw scrolling
*/
@@ -13290,6 +13430,7 @@ struct {
{ "check buttons", create_check_buttons },
{ "clist", create_clist},
{ "color selection", create_color_selection },
+ { "composited window", create_composited_window },
{ "ctree", create_ctree },
{ "cursors", create_cursors },
{ "dialog", create_dialog, TRUE },