Re: Our size allocation issues
- From: Owen Taylor <otaylor redhat com>
- To: Michael Meeks <michael ximian com>
- Cc: Alex Larsson <alexl redhat com>, nautilus-list gnome org, Gtk Hackers <gtk-devel-list gnome org>
- Subject: Re: Our size allocation issues
- Date: Wed, 21 Aug 2002 08:34:30 -0400 (EDT)
Michael Meeks <michael ximian com> writes:
> Hi Owen,
> Thank you for your detailed reply;
> On Tue, 2002-08-20 at 18:45, Owen Taylor wrote:
> > > Well; I add the plug at socket realize time [ or when
> > > the control is bound if the socket is already realized ].
> > I guess I should be happy that things work when you change
> > the widget heirarchy in a ::realize handler, but it really
> > isn't a terribly good idea.
> I'd like to know a better time to do the negotiation then - I can hook
> any signal / virtual method on the GtkWidget, it doesn't concern me. I
> have one requirement: that I be able to get a valid 'GdkScreen' for that
> widget. It's not at all clear to me how I can trap the "got valid
> screen" event - short of some bug riddled forest of add/remove signal
> handlers on distant parents of the GtkSocket. Any better ideas ? realize
> time seemed the obvious solution ?
It's not that hard to do ... tracking getting *a* valid screen
is simply tracking when the widget has been added to a toplevel ...
that is, the ::hierarchy-changed signal. Tracking the current
screen requires connecting to notify::screen on the current
toplevel; gtkfontsel and gtktoolbar do this.
But can you hook up a plug/socket before the socket is realized?
It might be able to be made work in the in-process case,
but the in-process case is basically just a short-circuiting
of the out-of-process case, so I don't think it's necessarily
a good idea to support that:
I wasn't suggesting that you hook up the socket
prior to realize, I was suggesting that you realize prior
to showing the toplevel, and wait for your plug/sockets to
get connected before you show the toplevel.
(Hard to do generically for Bonobo, but shouldn't be hard
for a specific case like the Nautilus desktop window.)
> > If I understand you, the reason why you are not getting
> > the right allocation on initial map is because GtkWindow::show
> > looks like:
> > a) size_request the toplevel
> > b) allocate the toplevel to the requested size
> > c) realize the toplevel
> > d) map the toplevel
> > And the plug is being added at c). We may be able to fix some
> > aspects of the problems from adding the socket at this point
> > within GtkSocket, but we aren't going to be able to fix all of them.
> > - We have to show _something_ where the plug appears until
> > the correct size gets figured out.
> Right; it'd be really nice to do the size_allocate on the Plug
> (in-process at least) during c) before the widget is mapped - thus I'm
> slightly suprised that:
> gtk_socket_size_allocate ()'s flow is much like:
> if (!GTK_WIDGET_REALIZED (socket))
> return; /* do nothing */
> So it appears that even if the plug is in-place, in-proc, associated
> with the socket, visible, but not realized by the time the toplevel is
> shown - the plug doesn't get an immediate allocate.
Only if the socket isn't realized and the plug is; and that's
definitely a borderline case....
> Why is it that we don't pass on the allocation to an in-proc GtkPlug ?
> and so on down the chain ? [ not that that helps me of course, since the
> size allocate happens before the realize & thus the insertion of the
> plug widget ]. However - with this 'fixed' and forcing an immediate size
> allocation on the socket as we add the plug would seem to get around the
> problem in-proc.
The *only* time non-core GTK+ code is allowed to call size_allocate()
is in a size_allocate() handler. While it may be possible to
do safely in some other circumstances, with the current core
GTK+ code, I really couldn't guarantee that it would continue
working in the future.
> > - If the requisition of the socket affects the size of the
> > toplevel, then you'll see a size bounce
> Ok - this is obviated in BonoboSocket / Plug by using CORBA to do the
> size requesting; otherwise you inevitably see a size bounce with out of
> proc components AFAIR, simply because the Plug can't be added until the
> GdkScreen is known which is realize time - and yet the requisition is
> ~independant of GdkScreen etc.
The requisition is most certainly not independent of the GdkScreen.
The theme and fonts depend on the GdkScreen.
> > I *think* it is probably possible to generically fix changing
> > the size requisition at C.... I won't go into the details
> I got lost here, but - if you say so; I wonder who will do this work ?
> I'd like to help - since the flicker annoys me and smells of a 'bonobo
> issue' to people.
What I meant is, that it wasn't something I could discuss as part
of a 200 line email, since it was complex in its own right :-). I'd be
happy to separately discuss it.
> > > > If you look at gtk_socket_add_window(), then in the out-of-process
> > > > case, it *doesn't* immediately map the plug; instead it
> > > > sets the need_map flag, and when a size_allocate() is received,
> > > > actually goes ahead and maps the child.
> > >
> > > I imagine it's intended that we pass the Xid of a mapped widget into
> > > the socket - and it hides it's GdkWindow until the re-parenting sizing
> > > is all sorted - such that the plug is mapped and it's XEMBED_MAPPED,
> > > STATE_WITHDRAWN settings are set - although it is really un-mapped /
> > > mapped by the Socket at least initially.
> > I'm having a little trouble following the above, but it seems that
> > you are describing the way XEMBED works, yes. Do you mean by "intended"
> > that there is a mismatch between intention and reality? What would
> > that be?
> Oh - the problem is simply that if the GtkPlug is realized, but not
> mapped: gtk_widget_realize (plug); gtk_plug_get_id (plug), that ID
> passed to the socket - then the socket does a gdk_window_show on the
> plug_window, and yet the plug's 'map' method was never called - thus the
> Xembed stuff doesn't get setup correctly. [it also renders garbage].
> That is, unless I misunderstand some process by which the plug is
> notified that it has been mapped. Thus it (seems) neccessary to me to
> assert that the GtkPlug IS_MAPPED when we get the XID from it; but this
> seems horribly counter-intuitive - surely we want to only realize and
> not show the GtkPlug before whacking it in the plug. I'm extremely
> confused here as I'm sure you can see.
I could believe that there is a bug in the in-process case if
you add a widget that you haven't yet shown to the parent.
I'm not sure why you would do that, but it should work.
If there is a bug there, please create a test case, file a
bug and we can handle that separately :-)
> Currently to get anything to work at all I have to 'gtk_widget_show'
> the plug, immediately after setting the gdk_screen on it - at the tail
> of step c) - before returning the plug's id to the parent. Doing a plain
> realize results in an ugly mess out of proc [ presumably because there
> is no way to notify the Plug's children when to be mapped (out of proc)
> during embedding in the socket ].
No, it's all supposed to work if you don't show an out-of-process
plug and add it to it's parent, then show later. I took considerable
care in the XEMBED protocol getting that right.
> > > * doing a gtk_widget_show (socket) propagates quickly
> > > through socket realize to gtk_container_map on the socket
> > > which again maps the widget; got around this with a
> > > gtk_socket_map handler that only maps if !need_map [
> > > need_map starts to be a inadequate name, perhaps we want
> > > delay_map_until_sized ]
> > Hmm, so, what you are doing is, for the in-process case, instead of
> > delaying mapping the plug window, delaying mapping the socket
> > window?
> Um; well - I simply copied the delayed mapping of the plug's GdkWindow
> - so in fact I was just delaying the mapping of the plug's window.
I don't understand your changes to gtk_socket_show() at all
> Anyhow - I'm rather confused as to how to proceed; where do you want
> this to go ?
There seem to be several directions here:
A) Nautilus specific hacks so that Nautilus doesn't stress
out the GTK+ system so much. This is definitely going
to give the best performance and appearance for Nautilus.
Anything else pretty much inevitably means gray flashes,
B) Making GtkWindow work better when the requisition of the
window changes at realization time.
C) Specific changes to GtkSocket/GtkPlug to make it do
"delay map until the allocation is received" for
in-process rather than out-of-process.
I'd be happy to discuss any or all of these (preferably separately).
I think C) is, to some extent, the least interesting. All you
can get with it is things appearing less bad rather than
] [Thread Prev