Re: Our size allocation issues
- From: Michael Meeks <michael ximian com>
- To: Owen Taylor <otaylor redhat 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: 20 Aug 2002 11:32:39 +0100
Hi Owen,
On Tue, 2002-08-20 at 00:21, Owen Taylor wrote:
> Let me see if I can describe how I expect things to work, and then
> perhaps you can correlate your observations with this.
Sounds good. I think the main problem is that I'm getting confused by
(possibly) two bugs.
The first is, that sizing seems erratic for some reason; fairly
frequently it seems that the GtkPlug side is not getting the
size_allocate propagated correctly from the GtkSocket (only when out of
process).
To see this, you can run libbonoboui/tests/test-reparent - re-sizing
the window (to greater than the GtkEntry default allocation) and then
hitting 'reparent widget' a few times. Of course, it's entirely possible
that I'm doing something daft - but having turned off all my (in some
cases mis-guided) Bonobo plug/socket shortcuts / optimizations I still
get the effect so ...
If I understood the process by which a size_allocate on the GtkSocket
resulted in a size_allocate on the remote GtkPlug then I'd be a lot
happier and might be able to debug the problem; how does that work ? [
via. a ConfigureEvent ? or do they merely go Plug -> Socket ? ].
> First, if I understand correctly, what we are discussing is the
> *in process* case of GtkPlug/GtkSocket?
Well; notwithstanding the above bug - yes.
> For any GTK+ widget, showing the widget after the parent is
> visible will result in the widget first being mapped with a
> bogus size (usually 1x1) and then moved to the new location
> when the idle size pass hits.
Sure; and you typically position that window at -1,-1 so that it's
invisible AFAIR.
> The easiest, and best, way of getting around this is to
> simply show your toplevels after all the widgets are in place;
> doing anything else is going to result in some flashing.
Having the out of proc case, as easy to use as in-proc containment
seems best in every way to me.
> For GtkSocket, you can tell when a child has been added
> to the socket using the ::plug-added signal.
Well; I add the plug at socket realize time [ or when the control is
bound if the socket is already realized ].
> Here we have a window that isn't 1x1 because the GtkPlug
> was allocated to it's requested size when it was mapped,
> prior to being added into the GtkSocket.
Right;
> I don't think trying to force the issue so that adding the plug
> to the socket forces an immediate size_allocate() on the socket
> is a good idea ... this is going to stress GTK+'s sizing system
> and could produce bad results when the size request of the plug
> forces the socket to resize.
Hmm; fair enough.
> But what you might want to look at instead is what happens
> for *out-of-process* Plug/Socket combos.
>
> 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 don't see any reason
> why we couldn't do the same thing in the in-process case.
I hacked something like this up; I hit the following problems:
* _gtk_plug_add_to_socket does a gtk_widget_set_parent
which does a 'map' if the parent is mapped; pre-empting
the need_map handling in size_allocate.
* 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 ]
Having done all of this, I have no flicker - at least in-proc, I
imagine the flicker will still be nasty out of process - at least it's
not clear to me how the socket's gdk_window_move_resize on the plug's
GdkWindow immediately before showing it will result in getting the out f
proc child's sub-windows / widgets layed out nicely before they're
mapped (?) but then perhaps that's handled by the normal mechanisms.
Anyway; the patch looks like this, although I'd also like to kill the
socket->same_app, since it's a synonym for socket->plug_widget != NULL;
and it's only used once.
? owen
? gdk/gdkmarshalers.h
? gtk/core.14631
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.3579
diff -u -p -u -r1.3579 ChangeLog
--- ChangeLog 19 Aug 2002 14:39:40 -0000 1.3579
+++ ChangeLog 20 Aug 2002 10:30:17 -0000
@@ -1,3 +1,16 @@
+2002-08-20 Michael Meeks <michael ximian com>
+
+ * gtk/gtksocket.c (gtk_socket_add_window): mark in-proc
+ windows for mapping on resize, always queue a resize.
+ (gtk_socket_map): only map the child if !need_map, else
+ just show the window.
+ (gtk_socket_size_allocate): do the delayed show in-proc too
+ (gtk_socket_class_init): upd.
+
+ * gtk/gtkplug.c (_gtk_plug_add_to_socket): hide the window
+ as we add it to the socket parent, tell the socket it needs
+ to map the child on sizing.
+
2002-08-19 Padraig O'Briain <padraig obriain sun com>
* gtk/gtkentry.c (gtk_entry_real_delete_text): Use
Index: gtk/gtkplug.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkplug.c,v
retrieving revision 1.57
diff -u -p -u -r1.57 gtkplug.c
--- gtk/gtkplug.c 20 Jun 2002 23:59:21 -0000 1.57
+++ gtk/gtkplug.c 20 Aug 2002 10:30:19 -0000
@@ -239,6 +239,8 @@ _gtk_plug_add_to_socket (GtkPlug *plug
if (GTK_WIDGET_REALIZED (widget))
{
gdk_drawable_get_size (GDK_DRAWABLE (widget->window), &w, &h);
+ gdk_window_hide (widget->window);
+ socket->need_map = TRUE;
gdk_window_reparent (widget->window, plug->socket_window, -w, -h);
}
Index: gtk/gtksocket.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksocket.c,v
retrieving revision 1.51
diff -u -p -u -r1.51 gtksocket.c
--- gtk/gtksocket.c 2 Jul 2002 16:22:19 -0000 1.51
+++ gtk/gtksocket.c 20 Aug 2002 10:30:20 -0000
@@ -78,6 +78,7 @@ static void gtk_socket_forall
gboolean include_internals,
GtkCallback callback,
gpointer callback_data);
+static void gtk_socket_map (GtkWidget *widget);
static void gtk_socket_add_window (GtkSocket *socket,
@@ -196,6 +197,7 @@ gtk_socket_class_init (GtkSocketClass *c
widget_class->grab_notify = gtk_socket_grab_notify;
widget_class->key_press_event = gtk_socket_key_press_event;
widget_class->focus = gtk_socket_focus;
+ widget_class->map = gtk_socket_map;
container_class->remove = gtk_socket_remove;
container_class->forall = gtk_socket_forall;
@@ -512,6 +514,12 @@ gtk_socket_size_allocate (GtkWidget
child_allocation.height = allocation->height;
gtk_widget_size_allocate (socket->plug_widget, &child_allocation);
+
+ if (socket->need_map)
+ {
+ gdk_window_show (socket->plug_window);
+ socket->need_map = FALSE;
+ }
}
else if (socket->plug_window)
{
@@ -998,7 +1006,7 @@ gtk_socket_add_window (GtkSocket
if (need_reparent)
{
- gdk_window_hide (socket->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
+ gdk_window_hide (socket->plug_window);
gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
}
@@ -1039,9 +1047,8 @@ gtk_socket_add_window (GtkSocket
gtk_get_current_event_time ());
socket_update_active (socket);
socket_update_focus_in (socket);
-
- gtk_widget_queue_resize (GTK_WIDGET (socket));
}
+ gtk_widget_queue_resize (GTK_WIDGET (socket));
if (socket->plug_window)
g_signal_emit (G_OBJECT (socket), socket_signals[PLUG_ADDED], 0);
@@ -1212,6 +1219,20 @@ unmap_notify (GtkSocket *socket)
{
socket->is_mapped = FALSE;
gtk_widget_queue_resize (GTK_WIDGET (socket));
+ }
+}
+
+static void
+gtk_socket_map (GtkWidget *widget)
+{
+ GtkSocket *socket = GTK_SOCKET (widget);
+
+ if (!socket->need_map)
+ GTK_WIDGET_CLASS (parent_class)->map (widget);
+ else
+ {
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ gdk_window_show (widget->window);
}
}
Comments ?
Michael.
--
mmeeks gnu org <><, Pseudo Engineer, itinerant idiot
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]