More notebook weirdness.

If you try the following program, you'll find that
the second page with the entry is momentarily
visible -- despite the fact that it should never
be shown at all.

What's going on here is that the notebook violates
the standard widget-system invariant:

   widget->parent && GTK_WIDGET_MAPPED (widget->parent) && 
     GTK_WIDGET_VISIBLE (widget) => GTK_WIDGET_MAPPED (widget)

Because non-visible pages are VISIBLE, but not MAPPED.
When a page is shown gtk_widget_real_show() calls
gtk_widget_map(), but a resize is also called at
the same time, and when that is processed,
gtk_notebook_size_request() notices that the page
should not be shown and hides it again.

There are various solutions

 1) Remove the invariant and the code in gtk_widget_real_show()
    enforcing it ... make each container responsible for 
    mapping its children if necessary. This seems poor in
    that it would break compatibility with existing containers.

 2) Give each page of the notebook its own GdkWindow. This
    way, the children can be left mapped all the time
    and only their parent-windows hidden and shown.

 3) Add an additional flag which means something like
    "parent wants this widget to be mapped".

2) is perhaps the easiest to do. But this problem may
well not be notebook-specific. In fact, I dealt with
pretty much the very same problem with GtkLayout a
couple of months ago... and actually added a flag
that sort of works like 3), though it only acts as a hint
to the drawing and resizing code.

So, perhaps this is an argument for going with 3). If
it is useful twice, it will be useful again?


#include <gtk/gtk.h>

gboolean timeout(gpointer data)
  gtk_widget_hide (data);
  gtk_widget_show (data);

  return TRUE;

int main (int argc, char **argv)
  GtkWidget *window, *notebook, *label, *button1, *entry;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  notebook = gtk_notebook_new ();
  gtk_container_add (GTK_CONTAINER (window), notebook);

  button1 = gtk_button_new_with_label ("Button #1");
  label = gtk_label_new ("Label #1");
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), button1, label);
  entry = gtk_entry_new ();
  label = gtk_label_new ("Label #2");
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook),  entry, label);
  gtk_widget_set_usize (entry, 100, 100);

  gtk_widget_show_all (window);

  gtk_timeout_add (100, timeout, entry);

  return TRUE;

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