summaryrefslogtreecommitdiffstats
path: root/gtk/src/ghbcompositor.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/src/ghbcompositor.c')
-rw-r--r--gtk/src/ghbcompositor.c207
1 files changed, 193 insertions, 14 deletions
diff --git a/gtk/src/ghbcompositor.c b/gtk/src/ghbcompositor.c
index 41ea67936..92f8fe2e8 100644
--- a/gtk/src/ghbcompositor.c
+++ b/gtk/src/ghbcompositor.c
@@ -45,12 +45,23 @@ enum {
static void ghb_compositor_finalize (GObject *object);
static void ghb_compositor_realize (GtkWidget *widget);
static void ghb_compositor_unrealize (GtkWidget *widget);
-static void ghb_compositor_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
static void ghb_compositor_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
+#if GTK_CHECK_VERSION(3, 0, 0)
+static gboolean ghb_compositor_draw (GtkWidget *widget,
+ cairo_t *cr);
+static void ghb_compositor_get_preferred_width(GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size);
+static void ghb_compositor_get_preferred_height(GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size);
+#else
static gboolean ghb_compositor_expose (GtkWidget *widget,
GdkEventExpose *event);
+static void ghb_compositor_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+#endif
static void ghb_compositor_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -93,14 +104,19 @@ ghb_compositor_class_init (GhbCompositorClass *class)
gobject_class->set_property = ghb_compositor_set_property;
gobject_class->get_property = ghb_compositor_get_property;
+#if GTK_CHECK_VERSION(3, 0, 0)
+ widget_class->draw = ghb_compositor_draw;
+ widget_class->get_preferred_width = ghb_compositor_get_preferred_width;
+ widget_class->get_preferred_height = ghb_compositor_get_preferred_height;
+#else
widget_class->size_request = ghb_compositor_size_request;
+ widget_class->expose_event = ghb_compositor_expose;
+#endif
widget_class->size_allocate = ghb_compositor_size_allocate;
widget_class->realize = ghb_compositor_realize;
widget_class->unrealize = ghb_compositor_unrealize;
- widget_class->expose_event = ghb_compositor_expose;
-
container_class->add = ghb_compositor_add;
container_class->remove = ghb_compositor_remove;
container_class->forall = ghb_compositor_forall;
@@ -425,7 +441,7 @@ ghb_compositor_forall(
GhbCompositorChild *cc;
GList *link, *next;
- for (link = compositor->children; link != NULL; link = link->next)
+ for (link = compositor->children; link != NULL; )
{
// The callback may cause the link to be removed from the list.
// So find next before calling callback
@@ -487,11 +503,15 @@ ghb_compositor_realize (GtkWidget *widget)
GdkWindow *window;
if (visible_window)
{
- attributes.visual = gtk_widget_get_visual (widget);
+#if GTK_CHECK_VERSION(3, 0, 0)
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+#else
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
attributes.colormap = gtk_widget_get_colormap (widget);
+#endif
+ attributes.visual = gtk_widget_get_visual (widget);
attributes.wclass = GDK_INPUT_OUTPUT;
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
window = gdk_window_new(gtk_widget_get_parent_window (widget),
&attributes, attributes_mask);
@@ -505,11 +525,13 @@ ghb_compositor_realize (GtkWidget *widget)
g_object_ref (window);
}
- widget->style = gtk_style_attach (widget->style, window);
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ gtk_widget_style_attach(widget);
if (visible_window)
gtk_style_set_background(widget->style, window,
GTK_STATE_NORMAL);
+#endif
}
static void
@@ -518,6 +540,60 @@ ghb_compositor_unrealize (GtkWidget *widget)
GTK_WIDGET_CLASS (ghb_compositor_parent_class)->unrealize (widget);
}
+#if GTK_CHECK_VERSION(3, 0, 0)
+static void
+ghb_compositor_get_preferred_width(
+ GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GhbCompositor *compositor = GHB_COMPOSITOR (widget);
+ GList *link;
+ GhbCompositorChild *cc;
+ gint width = 0;
+ GtkRequisition min_size, size;
+
+ for (link = compositor->children; link != NULL; link = link->next)
+ {
+ cc = (GhbCompositorChild*)link->data;
+ if (gtk_widget_get_visible(cc->widget))
+ {
+ gtk_widget_get_preferred_size(cc->widget, &min_size, &size);
+ width = MAX(MAX(min_size.width, size.width), width);
+ }
+ }
+
+ *minimum_size = width + gtk_container_get_border_width(GTK_CONTAINER (widget)) * 2;
+ *natural_size = width + gtk_container_get_border_width(GTK_CONTAINER (widget)) * 2;
+}
+
+static void
+ghb_compositor_get_preferred_height(
+ GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GhbCompositor *compositor = GHB_COMPOSITOR (widget);
+ GList *link;
+ GhbCompositorChild *cc;
+ gint height = 0;
+ GtkRequisition min_size, size;
+
+ for (link = compositor->children; link != NULL; link = link->next)
+ {
+ cc = (GhbCompositorChild*)link->data;
+ if (gtk_widget_get_visible(cc->widget))
+ {
+ gtk_widget_get_preferred_size(cc->widget, &min_size, &size);
+ height = MAX(MAX(min_size.height, size.height), height);
+ }
+ }
+
+ *minimum_size = height + gtk_container_get_border_width(GTK_CONTAINER (widget)) * 2;
+ *natural_size = height + gtk_container_get_border_width(GTK_CONTAINER (widget)) * 2;
+}
+#else
+
static void
ghb_compositor_size_request(
GtkWidget *widget,
@@ -527,23 +603,24 @@ ghb_compositor_size_request(
GList *link;
GhbCompositorChild *cc;
gint width = 0, height = 0;
- GtkRequisition child_requisition;
+ GtkRequisition size;
for (link = compositor->children; link != NULL; link = link->next)
{
cc = (GhbCompositorChild*)link->data;
if (gtk_widget_get_visible(cc->widget))
{
- gtk_widget_size_request(cc->widget, NULL);
- gtk_widget_get_child_requisition(cc->widget, &child_requisition);
- width = MAX(child_requisition.width, width);
- height = MAX(child_requisition.height, height);
+ //gtk_widget_size_request(cc->widget, NULL);
+ gtk_widget_size_request(cc->widget, &size);
+ width = MAX(size.width, width);
+ height = MAX(size.height, height);
}
}
requisition->width = width + gtk_container_get_border_width(GTK_CONTAINER (widget)) * 2;
requisition->height = height + gtk_container_get_border_width(GTK_CONTAINER (widget)) * 2;
}
+#endif
static void
ghb_compositor_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
@@ -553,7 +630,7 @@ ghb_compositor_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
GhbCompositorChild *cc;
GList *link;
- widget->allocation = *allocation;
+ gtk_widget_set_allocation(widget, allocation);
compositor = GHB_COMPOSITOR (widget);
if (!gtk_widget_get_has_window(widget))
@@ -593,6 +670,90 @@ ghb_compositor_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
}
}
+#if 0
+static void showrects(cairo_region_t *region)
+{
+ cairo_rectangle_int_t rect;
+ int ii;
+ int count = cairo_region_num_rectangles(region);
+
+ printf("rect count %d\n", count);
+ for (ii = 0; ii < count; ii++)
+ {
+ cairo_region_get_rectangle(region, ii, &rect);
+ printf("rect %d: %d,%d %dx%d\n",
+ ii, rect.x, rect.y, rect.width, rect.height);
+ }
+}
+#endif
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+static void
+ghb_compositor_blend (GtkWidget *widget, cairo_t *cr)
+{
+ GhbCompositor *compositor = GHB_COMPOSITOR (widget);
+ GList *link, *draw;
+ cairo_region_t *region;
+ GtkWidget *child;
+ GhbCompositorChild *cc;
+
+ if (compositor->children == NULL) return;
+ /* create a cairo context to draw to the window */
+
+ for (link = compositor->children; link != NULL; link = link->next)
+ {
+ cc = (GhbCompositorChild*)link->data;
+ for (draw = cc->drawables; draw != NULL; draw = draw->next)
+ {
+ GtkAllocation child_alloc;
+
+ /* get our child */
+ child = GTK_WIDGET(draw->data);
+
+ if (
+//!gtk_cairo_should_draw_window(cr, gtk_widget_get_window(child)) ||
+ !gtk_widget_get_visible(cc->widget) ||
+ !gtk_widget_get_visible(child))
+ continue;
+
+ gtk_widget_get_allocation(child, &child_alloc);
+ cairo_save(cr);
+
+ /* the source data is the (composited) event box */
+ gdk_cairo_set_source_window(cr, gtk_widget_get_window(child),
+ child_alloc.x,
+ child_alloc.y);
+
+ cairo_rectangle_int_t rect;
+
+ rect.x = child_alloc.x;
+ rect.y = child_alloc.y;
+ rect.width = child_alloc.width;
+ rect.height = child_alloc.height;
+
+ /* draw no more than our expose event intersects our child */
+ region = cairo_region_create_rectangle(&rect);
+
+ cairo_region_t *dregion = gdk_window_get_visible_region(
+ gtk_widget_get_window(child));
+ cairo_region_translate(dregion, child_alloc.x, child_alloc.y);
+ cairo_region_intersect(region, dregion);
+ cairo_region_destroy(dregion);
+
+ gdk_cairo_region(cr, region);
+ cairo_region_destroy(region);
+ cairo_clip(cr);
+
+ /* composite, with an opacity */
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_paint_with_alpha(cr, cc->opacity);
+
+ cairo_restore(cr);
+ }
+ }
+ /* we're done */
+}
+#else
static void
ghb_compositor_blend (GtkWidget *widget, GdkEventExpose *event)
{
@@ -631,6 +792,7 @@ ghb_compositor_blend (GtkWidget *widget, GdkEventExpose *event)
gtk_widget_get_window(child));
gdk_region_offset(dregion, child->allocation.x, child->allocation.y);
gdk_region_intersect (region, dregion);
+ gdk_region_destroy(dregion);
gdk_cairo_region (cr, region);
gdk_region_destroy(region);
@@ -644,7 +806,23 @@ ghb_compositor_blend (GtkWidget *widget, GdkEventExpose *event)
/* we're done */
cairo_destroy (cr);
}
+#endif
+#if GTK_CHECK_VERSION(3, 0, 0)
+static gboolean
+ghb_compositor_draw(GtkWidget *widget, cairo_t *cr)
+{
+ if (gtk_widget_is_drawable(widget))
+ {
+ if (gtk_widget_get_has_window(widget))
+ ghb_compositor_blend (widget, cr);
+
+ }
+ GTK_WIDGET_CLASS(ghb_compositor_parent_class)->draw(widget, cr);
+
+ return FALSE;
+}
+#else
static gboolean
ghb_compositor_expose (GtkWidget *widget, GdkEventExpose *event)
{
@@ -659,3 +837,4 @@ ghb_compositor_expose (GtkWidget *widget, GdkEventExpose *event)
return FALSE;
}
+#endif