gtkfixed.c 18.1 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
22
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 24
 */

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
/**
 * SECTION:gtkfixed
 * @Short_description: A container which allows you to position
 * widgets at fixed coordinates
 * @Title: GtkFixed
 *
 * The #GtkFixed widget is a container which can place child widgets
 * at fixed positions and with fixed sizes, given in pixels. #GtkFixed
 * performs no automatic layout management.
 *
 * For most applications, you should not use this container! It keeps
 * you from having to learn about the other GTK+ containers, but it
 * results in broken applications.  With #GtkFixed, the following
 * things will result in truncated text, overlapping widgets, and
 * other display bugs:
40 41 42 43
 *
 * - Themes, which may change widget sizes.
 *
 * - Fonts other than the one you used to write the app will of course
44 45 46 47
 *   change the size of widgets containing text; keep in mind that
 *   users may use a larger font because of difficulty reading the
 *   default, or they may be using Windows or the framebuffer port of
 *   GTK+, where different fonts are available.
48 49
 *
 * - Translation of text into other languages changes its size. Also,
50 51 52
 *   display of non-English text will use a different font in many
 *   cases.
 *
53
 * In addition, the fixed widget can’t properly be mirrored in
54 55
 * right-to-left languages such as Hebrew and Arabic. i.e. normally
 * GTK+ will flip the interface to put labels to the right of the
56
 * thing they label, but it can’t do that with #GtkFixed. So your
57 58 59 60 61 62 63 64 65 66 67 68
 * application will not be usable in right-to-left languages.
 *
 * Finally, fixed positioning makes it kind of annoying to add/remove
 * GUI elements, since you have to reposition all the other
 * elements. This is a long-term maintenance problem for your
 * application.
 *
 * If you know none of these things are an issue for your application,
 * and prefer the simplicity of #GtkFixed, by all means use the
 * widget. But you should be aware of the tradeoffs.
 */

69
#include "config.h"
70

Elliot Lee's avatar
Elliot Lee committed
71
#include "gtkfixed.h"
72

73
#include "gtkprivate.h"
Havoc Pennington's avatar
Havoc Pennington committed
74
#include "gtkintl.h"
75 76


77
struct _GtkFixedPrivate
78 79 80 81
{
  GList *children;
};

Havoc Pennington's avatar
Havoc Pennington committed
82 83 84 85 86
enum {
  CHILD_PROP_0,
  CHILD_PROP_X,
  CHILD_PROP_Y
};
Elliot Lee's avatar
Elliot Lee committed
87 88

static void gtk_fixed_realize       (GtkWidget        *widget);
89 90 91 92 93 94
static void gtk_fixed_get_preferred_width  (GtkWidget *widget,
                                            gint      *minimum,
                                            gint      *natural);
static void gtk_fixed_get_preferred_height (GtkWidget *widget,
                                            gint      *minimum,
                                            gint      *natural);
Elliot Lee's avatar
Elliot Lee committed
95
static void gtk_fixed_size_allocate (GtkWidget        *widget,
96
                                     GtkAllocation    *allocation);
97
static void gtk_fixed_style_updated (GtkWidget        *widget);
Benjamin Otte's avatar
Benjamin Otte committed
98 99
static gboolean gtk_fixed_draw      (GtkWidget        *widget,
                                     cairo_t          *cr);
Elliot Lee's avatar
Elliot Lee committed
100
static void gtk_fixed_add           (GtkContainer     *container,
101
                                     GtkWidget        *widget);
Elliot Lee's avatar
Elliot Lee committed
102
static void gtk_fixed_remove        (GtkContainer     *container,
103
                                     GtkWidget        *widget);
104
static void gtk_fixed_forall        (GtkContainer     *container,
105 106 107
                                     gboolean          include_internals,
                                     GtkCallback       callback,
                                     gpointer          callback_data);
Manish Singh's avatar
Manish Singh committed
108
static GType gtk_fixed_child_type   (GtkContainer     *container);
Elliot Lee's avatar
Elliot Lee committed
109

Havoc Pennington's avatar
Havoc Pennington committed
110 111 112 113 114 115 116 117 118 119
static void gtk_fixed_set_child_property (GtkContainer *container,
                                          GtkWidget    *child,
                                          guint         property_id,
                                          const GValue *value,
                                          GParamSpec   *pspec);
static void gtk_fixed_get_child_property (GtkContainer *container,
                                          GtkWidget    *child,
                                          guint         property_id,
                                          GValue       *value,
                                          GParamSpec   *pspec);
Elliot Lee's avatar
Elliot Lee committed
120

121
G_DEFINE_TYPE_WITH_PRIVATE (GtkFixed, gtk_fixed, GTK_TYPE_CONTAINER)
Elliot Lee's avatar
Elliot Lee committed
122 123 124 125 126 127 128 129 130 131 132

static void
gtk_fixed_class_init (GtkFixedClass *class)
{
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;

  widget_class = (GtkWidgetClass*) class;
  container_class = (GtkContainerClass*) class;

  widget_class->realize = gtk_fixed_realize;
133 134
  widget_class->get_preferred_width = gtk_fixed_get_preferred_width;
  widget_class->get_preferred_height = gtk_fixed_get_preferred_height;
Elliot Lee's avatar
Elliot Lee committed
135
  widget_class->size_allocate = gtk_fixed_size_allocate;
Benjamin Otte's avatar
Benjamin Otte committed
136
  widget_class->draw = gtk_fixed_draw;
137
  widget_class->style_updated = gtk_fixed_style_updated;
Elliot Lee's avatar
Elliot Lee committed
138 139 140

  container_class->add = gtk_fixed_add;
  container_class->remove = gtk_fixed_remove;
141
  container_class->forall = gtk_fixed_forall;
142
  container_class->child_type = gtk_fixed_child_type;
Havoc Pennington's avatar
Havoc Pennington committed
143 144
  container_class->set_child_property = gtk_fixed_set_child_property;
  container_class->get_child_property = gtk_fixed_get_child_property;
145
  gtk_container_class_handle_border_width (container_class);
Havoc Pennington's avatar
Havoc Pennington committed
146 147

  gtk_container_class_install_child_property (container_class,
148 149
                                              CHILD_PROP_X,
                                              g_param_spec_int ("x",
150 151
                                                                P_("X position"),
                                                                P_("X position of child widget"),
152
                                                                G_MININT, G_MAXINT, 0,
153
                                                                GTK_PARAM_READWRITE));
Havoc Pennington's avatar
Havoc Pennington committed
154 155

  gtk_container_class_install_child_property (container_class,
156 157
                                              CHILD_PROP_Y,
                                              g_param_spec_int ("y",
158 159
                                                                P_("Y position"),
                                                                P_("Y position of child widget"),
160
                                                                G_MININT, G_MAXINT, 0,
161
                                                                GTK_PARAM_READWRITE));
162 163
}

Manish Singh's avatar
Manish Singh committed
164
static GType
165
gtk_fixed_child_type (GtkContainer *container)
166 167
{
  return GTK_TYPE_WIDGET;
Elliot Lee's avatar
Elliot Lee committed
168 169 170 171 172
}

static void
gtk_fixed_init (GtkFixed *fixed)
{
173
  fixed->priv = gtk_fixed_get_instance_private (fixed);
174

175 176
  gtk_widget_set_has_window (GTK_WIDGET (fixed), FALSE);

177
  fixed->priv->children = NULL;
Elliot Lee's avatar
Elliot Lee committed
178 179
}

180 181 182 183 184 185 186
/**
 * gtk_fixed_new:
 *
 * Creates a new #GtkFixed.
 *
 * Returns: a new #GtkFixed.
 */
Elliot Lee's avatar
Elliot Lee committed
187
GtkWidget*
188
gtk_fixed_new (void)
Elliot Lee's avatar
Elliot Lee committed
189
{
Manish Singh's avatar
Manish Singh committed
190
  return g_object_new (GTK_TYPE_FIXED, NULL);
Elliot Lee's avatar
Elliot Lee committed
191 192
}

Havoc Pennington's avatar
Havoc Pennington committed
193 194 195 196
static GtkFixedChild*
get_child (GtkFixed  *fixed,
           GtkWidget *widget)
{
197
  GtkFixedPrivate *priv = fixed->priv;
Havoc Pennington's avatar
Havoc Pennington committed
198
  GList *children;
199

200
  for (children = priv->children; children; children = children->next)
Havoc Pennington's avatar
Havoc Pennington committed
201 202
    {
      GtkFixedChild *child;
203

Havoc Pennington's avatar
Havoc Pennington committed
204 205 206 207 208 209 210 211 212
      child = children->data;

      if (child->widget == widget)
        return child;
    }

  return NULL;
}

213 214 215 216 217 218 219 220 221
/**
 * gtk_fixed_put:
 * @fixed: a #GtkFixed.
 * @widget: the widget to add.
 * @x: the horizontal position to place the widget at.
 * @y: the vertical position to place the widget at.
 *
 * Adds a widget to a #GtkFixed container at the given position.
 */
Elliot Lee's avatar
Elliot Lee committed
222
void
223 224 225 226
gtk_fixed_put (GtkFixed  *fixed,
               GtkWidget *widget,
               gint       x,
               gint       y)
Elliot Lee's avatar
Elliot Lee committed
227
{
228
  GtkFixedPrivate *priv = fixed->priv;
Elliot Lee's avatar
Elliot Lee committed
229 230 231
  GtkFixedChild *child_info;

  g_return_if_fail (GTK_IS_FIXED (fixed));
232
  g_return_if_fail (GTK_IS_WIDGET (widget));
Elliot Lee's avatar
Elliot Lee committed
233 234 235 236 237 238 239 240

  child_info = g_new (GtkFixedChild, 1);
  child_info->widget = widget;
  child_info->x = x;
  child_info->y = y;

  gtk_widget_set_parent (widget, GTK_WIDGET (fixed));

241
  priv->children = g_list_append (priv->children, child_info);
Havoc Pennington's avatar
Havoc Pennington committed
242 243 244
}

static void
245 246 247 248
gtk_fixed_move_internal (GtkFixed      *fixed,
                         GtkFixedChild *child,
                         gint           x,
                         gint           y)
Havoc Pennington's avatar
Havoc Pennington committed
249 250
{
  g_return_if_fail (GTK_IS_FIXED (fixed));
251
  g_return_if_fail (gtk_widget_get_parent (child->widget) == GTK_WIDGET (fixed));
252

253
  gtk_widget_freeze_child_notify (child->widget);
Havoc Pennington's avatar
Havoc Pennington committed
254

255
  if (child->x != x)
Havoc Pennington's avatar
Havoc Pennington committed
256 257
    {
      child->x = x;
258
      gtk_widget_child_notify (child->widget, "x");
Havoc Pennington's avatar
Havoc Pennington committed
259 260
    }

261
  if (child->y != y)
Havoc Pennington's avatar
Havoc Pennington committed
262 263
    {
      child->y = y;
264
      gtk_widget_child_notify (child->widget, "y");
Havoc Pennington's avatar
Havoc Pennington committed
265 266
    }

267 268 269
  gtk_widget_thaw_child_notify (child->widget);

  if (gtk_widget_get_visible (child->widget) &&
270
      gtk_widget_get_visible (GTK_WIDGET (fixed)))
Havoc Pennington's avatar
Havoc Pennington committed
271
    gtk_widget_queue_resize (GTK_WIDGET (fixed));
Elliot Lee's avatar
Elliot Lee committed
272 273
}

274 275 276 277 278 279 280 281 282
/**
 * gtk_fixed_move:
 * @fixed: a #GtkFixed.
 * @widget: the child widget.
 * @x: the horizontal position to move the widget to.
 * @y: the vertical position to move the widget to.
 *
 * Moves a child of a #GtkFixed container to the given position.
 */
Elliot Lee's avatar
Elliot Lee committed
283
void
284 285 286 287
gtk_fixed_move (GtkFixed  *fixed,
                GtkWidget *widget,
                gint       x,
                gint       y)
Havoc Pennington's avatar
Havoc Pennington committed
288
{
289
  gtk_fixed_move_internal (fixed, get_child (fixed, widget), x, y);
Havoc Pennington's avatar
Havoc Pennington committed
290 291 292
}

static void
293 294 295 296 297
gtk_fixed_set_child_property (GtkContainer *container,
                              GtkWidget    *child,
                              guint         property_id,
                              const GValue *value,
                              GParamSpec   *pspec)
Elliot Lee's avatar
Elliot Lee committed
298
{
299 300 301 302 303
  GtkFixed *fixed = GTK_FIXED (container);
  GtkFixedChild *fixed_child;

  fixed_child = get_child (fixed, child);

Havoc Pennington's avatar
Havoc Pennington committed
304 305 306
  switch (property_id)
    {
    case CHILD_PROP_X:
307 308 309 310
      gtk_fixed_move_internal (fixed,
                               fixed_child,
                               g_value_get_int (value),
                               fixed_child->y);
Havoc Pennington's avatar
Havoc Pennington committed
311 312
      break;
    case CHILD_PROP_Y:
313 314 315 316
      gtk_fixed_move_internal (fixed,
                               fixed_child,
                               fixed_child->x,
                               g_value_get_int (value));
Havoc Pennington's avatar
Havoc Pennington committed
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
      break;
    default:
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
      break;
    }
}

static void
gtk_fixed_get_child_property (GtkContainer *container,
                              GtkWidget    *child,
                              guint         property_id,
                              GValue       *value,
                              GParamSpec   *pspec)
{
  GtkFixedChild *fixed_child;

  fixed_child = get_child (GTK_FIXED (container), child);
  
  switch (property_id)
    {
    case CHILD_PROP_X:
      g_value_set_int (value, fixed_child->x);
      break;
    case CHILD_PROP_Y:
      g_value_set_int (value, fixed_child->y);
      break;
    default:
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
      break;
    }
}

349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
static void
set_background (GtkWidget *widget)
{
  if (gtk_widget_get_realized (widget))
    {
      /* We still need to call gtk_style_context_set_background() here for
       * GtkFixed, since subclasses like EmacsFixed depend on the X window
       * background to be set.
       * This should be revisited next time we have a major API break.
       */
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
      gtk_style_context_set_background (gtk_widget_get_style_context (widget),
                                        gtk_widget_get_window (widget));
      G_GNUC_END_IGNORE_DEPRECATIONS;
    }
}

static void
gtk_fixed_style_updated (GtkWidget *widget)
{
  GTK_WIDGET_CLASS (gtk_fixed_parent_class)->style_updated (widget);

  set_background (widget);
}

Elliot Lee's avatar
Elliot Lee committed
374 375 376
static void
gtk_fixed_realize (GtkWidget *widget)
{
377 378
  GtkAllocation allocation;
  GdkWindow *window;
Elliot Lee's avatar
Elliot Lee committed
379 380 381
  GdkWindowAttr attributes;
  gint attributes_mask;

382
  if (!gtk_widget_get_has_window (widget))
Matthias Clasen's avatar
Matthias Clasen committed
383
    GTK_WIDGET_CLASS (gtk_fixed_parent_class)->realize (widget);
384 385
  else
    {
386
      gtk_widget_set_realized (widget, TRUE);
387

388 389
      gtk_widget_get_allocation (widget, &allocation);

390
      attributes.window_type = GDK_WINDOW_CHILD;
391 392 393 394
      attributes.x = allocation.x;
      attributes.y = allocation.y;
      attributes.width = allocation.width;
      attributes.height = allocation.height;
395 396 397 398
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.visual = gtk_widget_get_visual (widget);
      attributes.event_mask = gtk_widget_get_events (widget);
      attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
399

400
      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
401 402 403 404

      window = gdk_window_new (gtk_widget_get_parent_window (widget),
                               &attributes, attributes_mask);
      gtk_widget_set_window (widget, window);
405
      gtk_widget_register_window (widget, window);
406

407
      set_background (widget);
408
    }
Elliot Lee's avatar
Elliot Lee committed
409 410 411
}

static void
412 413 414
gtk_fixed_get_preferred_width (GtkWidget *widget,
                               gint      *minimum,
                               gint      *natural)
Elliot Lee's avatar
Elliot Lee committed
415
{
416 417
  GtkFixed *fixed = GTK_FIXED (widget);
  GtkFixedPrivate *priv = fixed->priv;
Elliot Lee's avatar
Elliot Lee committed
418 419
  GtkFixedChild *child;
  GList *children;
420
  gint child_min, child_nat;
Elliot Lee's avatar
Elliot Lee committed
421

422 423
  *minimum = 0;
  *natural = 0;
424

425
  for (children = priv->children; children; children = children->next)
Elliot Lee's avatar
Elliot Lee committed
426 427 428
    {
      child = children->data;

429 430 431 432 433
      if (!gtk_widget_get_visible (child->widget))
        continue;

      gtk_widget_get_preferred_width (child->widget, &child_min, &child_nat);

434 435
      *minimum = MAX (*minimum, child->x + child_min);
      *natural = MAX (*natural, child->x + child_nat);
Elliot Lee's avatar
Elliot Lee committed
436
    }
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
}

static void
gtk_fixed_get_preferred_height (GtkWidget *widget,
                                gint      *minimum,
                                gint      *natural)
{
  GtkFixed *fixed = GTK_FIXED (widget);
  GtkFixedPrivate *priv = fixed->priv;
  GtkFixedChild *child;
  GList *children;
  gint child_min, child_nat;

  *minimum = 0;
  *natural = 0;

  for (children = priv->children; children; children = children->next)
    {
      child = children->data;

      if (!gtk_widget_get_visible (child->widget))
        continue;

      gtk_widget_get_preferred_height (child->widget, &child_min, &child_nat);
Elliot Lee's avatar
Elliot Lee committed
461

462 463 464
      *minimum = MAX (*minimum, child->y + child_min);
      *natural = MAX (*natural, child->y + child_nat);
    }
Elliot Lee's avatar
Elliot Lee committed
465 466 467 468
}

static void
gtk_fixed_size_allocate (GtkWidget     *widget,
469
                         GtkAllocation *allocation)
Elliot Lee's avatar
Elliot Lee committed
470
{
471
  GtkFixed *fixed = GTK_FIXED (widget);
472
  GtkFixedPrivate *priv = fixed->priv;
Elliot Lee's avatar
Elliot Lee committed
473 474
  GtkFixedChild *child;
  GtkAllocation child_allocation;
475
  GtkRequisition child_requisition;
Elliot Lee's avatar
Elliot Lee committed
476 477
  GList *children;

478
  gtk_widget_set_allocation (widget, allocation);
Elliot Lee's avatar
Elliot Lee committed
479

480
  if (gtk_widget_get_has_window (widget))
481
    {
482
      if (gtk_widget_get_realized (widget))
483 484 485 486 487
        gdk_window_move_resize (gtk_widget_get_window (widget),
                                allocation->x,
                                allocation->y,
                                allocation->width,
                                allocation->height);
488
    }
489

490
  for (children = priv->children; children; children = children->next)
Elliot Lee's avatar
Elliot Lee committed
491 492
    {
      child = children->data;
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509

      if (!gtk_widget_get_visible (child->widget))
        continue;

      gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
      child_allocation.x = child->x;
      child_allocation.y = child->y;

      if (!gtk_widget_get_has_window (widget))
        {
          child_allocation.x += allocation->x;
          child_allocation.y += allocation->y;
        }

      child_allocation.width = child_requisition.width;
      child_allocation.height = child_requisition.height;
      gtk_widget_size_allocate (child->widget, &child_allocation);
Elliot Lee's avatar
Elliot Lee committed
510 511 512 513 514
    }
}

static void
gtk_fixed_add (GtkContainer *container,
515
               GtkWidget    *widget)
Elliot Lee's avatar
Elliot Lee committed
516 517 518 519 520 521
{
  gtk_fixed_put (GTK_FIXED (container), widget, 0, 0);
}

static void
gtk_fixed_remove (GtkContainer *container,
522
                  GtkWidget    *widget)
Elliot Lee's avatar
Elliot Lee committed
523
{
524
  GtkFixed *fixed = GTK_FIXED (container);
525
  GtkFixedPrivate *priv = fixed->priv;
Elliot Lee's avatar
Elliot Lee committed
526
  GtkFixedChild *child;
527
  GtkWidget *widget_container = GTK_WIDGET (container);
Elliot Lee's avatar
Elliot Lee committed
528 529
  GList *children;

530
  for (children = priv->children; children; children = children->next)
Elliot Lee's avatar
Elliot Lee committed
531 532 533 534
    {
      child = children->data;

      if (child->widget == widget)
535 536 537 538
        {
          gboolean was_visible = gtk_widget_get_visible (widget);

          gtk_widget_unparent (widget);
Elliot Lee's avatar
Elliot Lee committed
539

540 541 542
          priv->children = g_list_remove_link (priv->children, children);
          g_list_free (children);
          g_free (child);
Elliot Lee's avatar
Elliot Lee committed
543

544 545
          if (was_visible && gtk_widget_get_visible (widget_container))
            gtk_widget_queue_resize (widget_container);
Elliot Lee's avatar
Elliot Lee committed
546

547 548
          break;
        }
Elliot Lee's avatar
Elliot Lee committed
549 550 551 552
    }
}

static void
553
gtk_fixed_forall (GtkContainer *container,
554 555 556
                  gboolean      include_internals,
                  GtkCallback   callback,
                  gpointer      callback_data)
Elliot Lee's avatar
Elliot Lee committed
557
{
558
  GtkFixed *fixed = GTK_FIXED (container);
559
  GtkFixedPrivate *priv = fixed->priv;
Elliot Lee's avatar
Elliot Lee committed
560 561 562
  GtkFixedChild *child;
  GList *children;

563 564
  children = priv->children;
  while (children)
Elliot Lee's avatar
Elliot Lee committed
565 566
    {
      child = children->data;
567
      children = children->next;
Elliot Lee's avatar
Elliot Lee committed
568 569 570 571

      (* callback) (child->widget, callback_data);
    }
}
Benjamin Otte's avatar
Benjamin Otte committed
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595

static gboolean
gtk_fixed_draw (GtkWidget *widget,
                cairo_t   *cr)
{
  GtkFixed *fixed = GTK_FIXED (widget);
  GtkFixedPrivate *priv = fixed->priv;
  GtkFixedChild *child;
  GList *list;

  for (list = priv->children;
       list;
       list = list->next)
    {
      child = list->data;

      gtk_container_propagate_draw (GTK_CONTAINER (fixed),
                                    child->widget,
                                    cr);
    }
  
  return FALSE;
}