Re: Our size allocation issues



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]