compositing + shape mask in gtk+ 2.18



I have a custom widget I've created that allows a collection of widgets
to be stacked and composited.  Each widgets opacity can be individually
set when added to the zlist of the compositing widget.  I use this to
create popup overlays for displaying controls over a video background.
All widgets added to the compositor must have associated GdkDrawable's
for compositing to work.

The problem I have is with widgets that I've set a shape mask on with
gtk_widget_shape_combine_mask().  When drawn for the first time after
showing the widget, the shape is respected and I get the output I
expect.  But when one of the widgets that is lower in the zlist changes,
the parts of the shaped widget that should be transparent maintain the
pixels from the previous rendering of the widget that changed beneath it. 

This used to work and stopped working with gtk+ 2.18.  I'm wondering if
it is related to the introduction of child-side windows.

Here's what the expose event code that does the compositing looks like. 
Anyone see something I should be doing differently?

static void
ghb_compositor_blend (GtkWidget *widget, GdkEventExpose *event)
{
    GhbCompositor *compositor = GHB_COMPOSITOR (widget);
    GList *link, *draw;
    GdkRegion *region;
    GtkWidget *child;
    cairo_t *cr;
    GhbCompositorChild *cc;

    if (compositor->children == NULL) return;
    /* create a cairo context to draw to the window */
    cr = gdk_cairo_create (widget->window);

    for (link = compositor->children; link != NULL; link = link->next)
    {

        cc = (GhbCompositorChild*)link->data;
        for (draw = cc->drawables; draw != NULL; draw = draw->next)
        {
            /* get our child */
            child = GTK_WIDGET(draw->data);
            if (!GTK_WIDGET_VISIBLE(cc->widget) ||
                !GTK_WIDGET_VISIBLE(child))
                continue;

            /* 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 an opacity */
            cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
            cairo_paint_with_alpha (cr, cc->opacity);
            cairo_reset_clip(cr);
        }
    }
    /* we're done */
    cairo_destroy (cr);
}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]