[Gtk-sharp-list] Widget.Toplevel on Menu widgets

Bruno Fernandez-Ruiz brunofr@olympum.com
21 Aug 2003 02:15:57 +0300


Hi

I am building an application with glade/gtk-sharp that creates multiple
instances of the same top level window, and I have found a few problems
with Gtk.Widget.Toplevel. I wonder if more people have also faced
something like this.

Calling Toplevel on a widget is supposed to return either the topmost
ancestor of the widget or the widget itself if there is no ancestor. 
However calling toplevel on a widget that contains a Menu widget in its
hierarchy does not seem to work correctly, as the pointer to the
returned toplevel window does not correspond to the expected correct
pointer.

I found a reference in fairly outdated gnome lists:

http://mail.gnome.org/archives/gtk-list/2001-December/msg00072.html

Has anybody experienced this before with Toplevel and Menus?

This hack, although ugly, seems to work (with one limitation) and bypass
the Menu problem:

private Gtk.Widget GetToplevelWidget (Gtk.Widget w) {	
	Gtk.Widget widget = w;
	Gtk.Widget parent = null;
	for (;;) {
		if (widget is Gtk.Menu) {
			Gtk.Menu menu = widget as Gtk.Menu;
			parent = menu.AttachWidget;
		} else {
			// This hack won't work with windows
			// that are not toplevel
			if (widget is Gtk.Window) {
				break;
			}
			parent = widget.Parent;
		}
		if (parent == null) {
			break;
		}
		widget = parent;
	}
	return widget;
}


The limitation is that when I match the Gtk.Window in the hierarchy, I
have to stop (otherwise I would get an exception) and possibly miss the
case that the window is not Toplevel but Popup.

I have created a little test to show the exception:

// ...
Application.Init ();
Gtk.Window w = new Gtk.Window ("Hi");
w.Show ();
Widget widget = w.Parent;
Application.Run ();
// ...

which when run ...

Unhandled Exception: System.NullReferenceException: A null value was
found where an object instance was required
in (unmanaged) 06 Gtk.Object:gtksharp_object_is_floating (intptr)
in <0x00004> 06 Gtk.Object:gtksharp_object_is_floating (intptr)
in <0x0001b> 00 Gtk.Object:set_Raw (intptr)
in <0x00023> 00 GLib.Object:.ctor (intptr)
in <0x0003b> 00 Gtk.Object:.ctor (intptr)
in <0x0003b> 00 Gtk.Widget:.ctor (intptr)
in <0x000e9> 00 Gtk.Widget:get_Parent ()
in <0x000a3> 00 .ToplevelTest:Main ()

Based on the API docs, I would expect a null to be returned for toplevel
widgets.

However on the generated Widget.cs using CVS HEAD, I see in get_Parent:

// ... line 76
if (ret == null) ret = new Gtk.Widget(raw_ret);
return ret;

and obviously raw_ret is null, and so should be ret. 

I don't really know how the code generator works, and I am not even sure
of whether this is the actual problem or not as I am fairly new to
programming with gtk+, otherwise I would fix this myself :)

The generated code that I would think to be correct is:
// ... line 76
if (ret == null) {
	if (raw_ret != null) {
		ret = new Gtk.Widget(raw_ret);
	}
}
return ret;

Sorry about the long post. I hope it helps ... and I hope I can help ;)

Bruno

-- 
Bruno Fernandez-Ruiz <brunofr@olympum.com>
http://www.simetron.org