summaryrefslogtreecommitdiff
path: root/gtk/gtkcontainer.c
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2001-03-09 13:28:26 +0000
committerAlexander Larsson <alexl@src.gnome.org>2001-03-09 13:28:26 +0000
commite7d4a7f90d58e7e45bf690107b3615135ced357e (patch)
treebab1f3860394d2c5f4ca39a4710cd078baaa37fc /gtk/gtkcontainer.c
parent8f35f03045bd7d9e6a75ad07ac2dae32e5aa8ae1 (diff)
downloadgtk+-e7d4a7f90d58e7e45bf690107b3615135ced357e.tar.gz
Document expose event->region change and that gtk_widget_event doesn't
2001-03-09 Alexander Larsson <alexl@redhat.com> * docs/Changes-2.0.txt: Document expose event->region change and that gtk_widget_event doesn't allow passing expose events. * gdk/gdkevents.h: Add region to expose event. * gdk/gdkevents.c: Handle event->region in gdk_event_copy() and gdk_event_free(). * gdk/gdkwindow.c (gdk_window_process_updates_internal): Generate expose_event->region when creating expose events. * gdk/x11/gdkevents-x11.c: Generate expose events with regions when translating X events. * gtk/gtkcontainer.[ch]: Default expose handler that propagates expose events to NO_WINDOW children. New function gtk_container_propagate_expose() * gtk/gtkwidget.[ch]: Moved gtk_widget_event implementation to gtk_widget_event_internal. gtk_widget_event calls gtk_widget_event_internal but doesn't allow expose events. New function gtk_widget_send_expose() to send expose events. New function gtk_widget_region_intersect() to calculate window/region intersections. * gtk/gtkmain.c (gtk_main_do_event): Use gdk_window_begin_paint_region() instead of gdk_window_begin_paint_rect(). Use gtk_widget_send_expose() to send expose events. * gtk/gtkbin.c: * gtk/gtkbox.c: * gtk/gtkfixed.c: * gtk/gtkimagemenuitem.c: * gtk/gtklist.c: * gtk/gtkpacker.c: * gtk/gtktable.c: * gtk/gtktree.c: Remove expose handler, using the default container implementation instead. * gtk/gtkbutton.c: * gtk/gtkcheckbutton.c: * gtk/gtkeventbox.c: * gtk/gtkfixed.c: * gtk/gtkhandlebox.c: * gtk/gtklayout.c: * gtk/gtklistitem.c: * gtk/gtkmenu.c: * gtk/gtkmenubar.c: * gtk/gtkmenuitem.c: * gtk/gtknotebook.c: * gtk/gtkoptionmenu.c: * gtk/gtkpaned.c: * gtk/gtkscrolledwindow.c: * gtk/gtktogglebutton.c: * gtk/gtktoolbar.c: * gtk/gtktreeitem.c: * gtk/gtkviewport.c: Chain expose handler to parent class handler. Use gtk_container_propagate_expose() to propagate exposes. * gtk/gtkclist.c (check_exposures): * gtk/gtktext.c (process_exposes): Use gtk_widget_send_expose instead of gtk_widget_event.
Diffstat (limited to 'gtk/gtkcontainer.c')
-rw-r--r--gtk/gtkcontainer.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 8a62957819..760e152966 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -96,6 +96,8 @@ static void gtk_container_children_callback (GtkWidget *widget,
gpointer client_data);
static void gtk_container_show_all (GtkWidget *widget);
static void gtk_container_hide_all (GtkWidget *widget);
+static gint gtk_container_expose (GtkWidget *widget,
+ GdkEventExpose *event);
static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
@@ -172,6 +174,7 @@ gtk_container_class_init (GtkContainerClass *class)
widget_class->show_all = gtk_container_show_all;
widget_class->hide_all = gtk_container_hide_all;
+ widget_class->expose_event = gtk_container_expose;
class->add = gtk_container_add_unimplemented;
class->remove = gtk_container_remove_unimplemented;
@@ -1963,3 +1966,95 @@ gtk_container_hide_all (GtkWidget *widget)
(GtkCallback) gtk_widget_hide_all,
NULL);
}
+
+
+static void
+gtk_container_expose_child (GtkWidget *child,
+ gpointer client_data)
+{
+ struct {
+ GtkWidget *container;
+ GdkEventExpose *event;
+ } *data = client_data;
+
+ gtk_container_propagate_expose (GTK_CONTAINER (data->container),
+ child,
+ data->event);
+}
+
+static gint
+gtk_container_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ struct {
+ GtkWidget *container;
+ GdkEventExpose *event;
+ } data;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CONTAINER (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ data.container = widget;
+ data.event = event;
+
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_container_expose_child,
+ &data);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * gtk_container_propagate_expose:
+ * @container: a #GtkContainer
+ * @child: a child of @container
+ * @event: a expose event sent to container
+ *
+ * When a container receives an expose event, it must send synthetic
+ * expose events to all children that don't have their own GdkWindows.
+ * This function provides a convenient way of doing this. A container,
+ * when it receives an expose event, gtk_container_propagate_expose()
+ * once for each child, passing in the event the container received.
+ *
+ * gtk_container_propagate expose() takes care of deciding whether
+ * an expose event needs to be sent to the child, intersecting
+ * the event's area with the child area, and sending the event.
+ *
+ * In most cases, a container can simply either simply inherit the
+ * ::expose implementation from GtkContainer, or, do some drawing
+ * and then chain to the ::expose implementation from GtkContainer.
+ **/
+void
+gtk_container_propagate_expose (GtkContainer *container,
+ GtkWidget *child,
+ GdkEventExpose *event)
+{
+ GdkEventExpose child_event;
+
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (event != NULL);
+
+ g_assert (child->parent == GTK_WIDGET (container));
+
+ if (GTK_WIDGET_DRAWABLE (child) &&
+ GTK_WIDGET_NO_WINDOW (child) &&
+ (child->window == event->window))
+ {
+ child_event = *event;
+
+ child_event.region = gtk_widget_region_intersect (child, event->region);
+ if (!gdk_region_empty (child_event.region))
+ {
+ gdk_region_get_clipbox (child_event.region, &child_event.area);
+ gtk_widget_send_expose (child, (GdkEvent *)&child_event);
+ }
+ gdk_region_destroy (child_event.region);
+ }
+}