GtkBin also provides default
implementations of expose, map, unmap, and draw from
GtkWidgetClass. Most
GtkBin subclasses will
override these methods to handle the unique features of
the subclass, but chain up to the GtkBin method to deal with their child
widget.
The GtkBin map and unmap
implementations are mostly the usual boilerplate (set
GTK_MAPPED, show widget->window) but they
add an important step unique to containers: mapping the
child if it has been shown (remember that GTK_VISIBLE signals a widget has
been shown), and unmapping the child when the bin is
unmapped. Here's the code:
static void
gtk_bin_map (GtkWidget *widget)
{
GtkBin *bin;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_BIN (widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
bin = GTK_BIN (widget);
if (bin->child &&
GTK_WIDGET_VISIBLE (bin->child) &&
!GTK_WIDGET_MAPPED (bin->child))
gtk_widget_map (bin->child);
if (!GTK_WIDGET_NO_WINDOW (widget))
gdk_window_show (widget->window);
}
static void
gtk_bin_unmap (GtkWidget *widget)
{
GtkBin *bin;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_BIN (widget));
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
bin = GTK_BIN (widget);
if (GTK_WIDGET_NO_WINDOW (widget))
gtk_widget_queue_clear (widget);
else
gdk_window_hide (widget->window);
if (bin->child && GTK_WIDGET_MAPPED (bin->child))
gtk_widget_unmap (bin->child);
}
|
GtkBin's draw and expose
implementations simply redraw the child widget; most
subclasses will need to override these methods in order
to draw themselves, then chain up to draw the child.
The code:
static void
gtk_bin_draw (GtkWidget *widget,
GdkRectangle *area)
{
GtkBin *bin;
GdkRectangle child_area;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_BIN (widget));
bin = GTK_BIN (widget);
if (GTK_WIDGET_DRAWABLE (bin))
{
if (bin->child && GTK_WIDGET_DRAWABLE (bin->child) &&
gtk_widget_intersect (bin->child, area, &child_area))
gtk_widget_draw (bin->child, &child_area);
}
}
static gint
gtk_bin_expose (GtkWidget *widget,
GdkEventExpose *event)
{
GtkBin *bin;
GdkEventExpose child_event;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_BIN (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (GTK_WIDGET_DRAWABLE (widget))
{
bin = GTK_BIN (widget);
child_event = *event;
if (bin->child && GTK_WIDGET_DRAWABLE (bin->child) &&
GTK_WIDGET_NO_WINDOW (bin->child) &&
gtk_widget_intersect (bin->child, &event->area, &child_event.area))
gtk_widget_event (bin->child, (GdkEvent*) &child_event);
}
return FALSE;
}
|
Notice that expose events are only generated for
windowless widgets; widgets with windows will receive
their own expose events. Containers are required to
generate expose events for windowless children.
You can probably guess that
gtk_widget_intersect() determines the intersection
of a rectangle and a child widget.