Update to Canvas Component Fixes



Hello,

	This is an update to a previous posting that I sent in April.  Since
the last posting I have cleaned up a misuse of the gdk threads mutex as
well as fixed several other bugs that I stumbled across while
investigating some of the synchronization issues.

	In the last posting I claimed I had it working "perfectly". I won't
make this claim again, but I will say it I don't have any test case that
breaks it at the moment.

The change logs from CVS head (not from the last posting) are below.

Bob Gibbs.

=============================================================================

ChangeLog:

bonobo-canvas-component.h

(bonobo_canvas_component_factory_new): new.  Convenience to replace old
embeddable way of creating the canvas component.

bonobo-canvas-component.c

(impl_Bonobo_Canvas_Component_bounds): Mapped state for crossing event.

(impl_Bonobo_Canvas_Component_contains): Fixed to return proper
inside/outside
value.  Was always returning true.

(impl_Bonobo_Canvas_Component_update): Call rih group update here vice
inside
rih_update. Solves for case where a request_update is made while the
component
is waiting for a response.

(handle_event): new. Passes the remote item's event back into the
local pseudo-canvas so that canvas items can see events the normal way
as if
they were not using bonobo.

(rih_update): Moved rih group update into
impl_Bonobo_Canvas_Component_update.
This solves for case where a request_update is made while the component
is
waiting for a response to its last
Bonobo_Canvas_ComponentProxy_requestUpdate.

(impl_Bonobo_Canvas_Component_event): Added do_update_flag check to
prevent
signal from being emitted when any pseudo-canvas is in its do_update.
Fixed
alloc/de-alloc of gdk_event structure.

(handle_event_later): new. Emits event signal sometime after do_update
finishes.

(free_event): removed. Replaced by gdk_event_free.

(impl_Bonobo_Canvas_Component_setBounds): Added do_update_flag check to
prevent
signal from being emitted when any pseudo-canvas is in its do_update.
This
procedure is in IDL but does not appear to be invoke by the client ever.

(set_bounds_later):  new. Emits bounds signal sometime after do_update
finishes.

(bonobo_canvas_new): Put into container to prevent gtk warning.

(bonobo_canvas_component_factory_new): new.  Convenience to replace old
embeddable way of creating the canvas component.

bonobo-canvas-item.c

(gbi_set_property): Moved proxy_size_allocate call from gbi_set_property
to
gbi_realize. Sometimes widget is not realized when user sets the
properties.

(gdk_event_to_bonobo_event): fixed x/y mixup for motion notify

(bonobo_canvas_item_class_init): Make sure set_property callback is
initialized
before calling install_property.

(impl_Bonobo_Canvas_ComponentProxy_requestUpdate): Added idle_handler
that
gets invoked whenever the canvas has already had one added.  This solves
for
case of NEED_UPDATE flags getting out of sync and canvas refusing to
update the
remote item forever thereafter. See code for further details.

(create_proxy): Fixed to allocate space for base epv before
initializing.


=============================================================================
--- bonobo-canvas-component.h.orig	Wed Jan 22 09:23:17 2003
+++ bonobo-canvas-component.h	Tue Apr 15 08:31:43 2003
@@ -27,12 +27,11 @@
 #define BONOBO_IS_CANVAS_COMPONENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE
((k), BONOBO_TYPE_CANVAS_COMPONENT))
 
 typedef struct _BonoboCanvasComponentPrivate
BonoboCanvasComponentPrivate;
-typedef struct _BonoboCanvasComponent        BonoboCanvasComponent;
 
-struct _BonoboCanvasComponent {
+typedef struct {
 	BonoboObject base;
 	BonoboCanvasComponentPrivate *priv;
-};
+} BonoboCanvasComponent;
 
 typedef struct {
 	BonoboObjectClass parent_class;
@@ -70,6 +69,16 @@
 GnomeCanvas *bonobo_canvas_new (gboolean                     is_aa,
 				Bonobo_Canvas_ComponentProxy proxy);
 
+
+/* Sets up a callback to be invoked when the container activates the
object.
+ * Creating the component factory will do nothing until the container
connects.
+ */
+typedef BonoboCanvasComponent *(*GnomeItemCreator) 
+   (GnomeCanvas *canvas, void *user_data);
+
+BonoboObject *bonobo_canvas_component_factory_new(GnomeItemCreator
item_factory,
+      void *data);
+
 G_END_DECLS
 
 #endif /* BONOBO_UI_DISABLE_DEPRECATED */


=============================================================================
--- bonobo-canvas-component.c.orig	Wed Feb 13 11:30:45 2002
+++ bonobo-canvas-component.c	Mon May  5 20:25:17 2003
@@ -16,10 +16,13 @@
 #include <libgnomecanvas/gnome-canvas.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdkprivate.h>
+#include <gtk/gtk.h>
 #include <bonobo/bonobo-exception.h>
 #include <bonobo/bonobo-ui-component.h>
 #include <bonobo/bonobo-canvas-component.h>
 #include <bonobo/bonobo-ui-marshal.h>
+#undef BONOBO_DISABLE_DEPRECATED
+#include <bonobo/bonobo-xobject.h>
 
 enum {
 	SET_BOUNDS,
@@ -43,6 +46,15 @@
 
 static GObjectClass *gcc_parent_class;
 
+static gboolean do_update_flag = FALSE;
+
+typedef struct
+{
+        gpointer *arg1;
+        gpointer *arg2;
+} EmitLater;
+
+
 static gboolean
 CORBA_SVP_Segment_to_SVPSeg (Bonobo_Canvas_SVPSegment *seg, ArtSVPSeg
*art_seg)
 {
@@ -194,6 +206,9 @@
 	ArtSVP *svp = NULL;
 	Bonobo_Canvas_ArtUTA *cuta;
 
+	GnomeCanvasItemClass *gci_class = gtk_type_class (
+					gnome_canvas_item_get_type ());
+
 	restore_state (item, state);
 	for (i = 0; i < 6; i++)
 		affine [i] = aff [i];
@@ -221,7 +236,7 @@
 			}
 		}
 	}
-	
+
 	invoke_update (item, (double *)aff, svp, flags);
 
 	if (svp){
@@ -247,6 +262,10 @@
 	/*
 	 * Now, mark our canvas as fully up to date
 	 */
+
+        /* Clears flags for root item. */
+	(* gci_class->update) (item->canvas->root, affine, svp, flags);
+
 	if (item->canvas->redraw_area) {
 		art_uta_free (item->canvas->redraw_area);
 		item->canvas->redraw_area = NULL;
@@ -416,14 +435,19 @@
 {
 	Gcc *gcc = GCC (bonobo_object_from_servant (servant));
 	GnomeCanvasItem *item = GNOME_CANVAS_ITEM (gcc->priv->item);
-	GnomeCanvasItem *new_item;
+        GnomeCanvasItem *new_item;
+        int cx, cy;
 	CORBA_boolean ret;
-	
+
+        gnome_canvas_w2c (item->canvas, x, y, &cx, &cy);
+
 	if (getenv ("CC_DEBUG"))
 		printf ("Point %g %g: ", x, y);
-	ret = ICLASS (item)->point (item, x, y, 0, 0, &new_item) == 0.0;
+	ret = ICLASS (item)->point (item, x, y, cx, cy, &new_item) == 0.0 &&
+                new_item != NULL;
 	if (getenv ("CC_DEBUG"))
 		printf ("=> %s\n", ret ? "yes" : "no");
+	
 	return ret;
 }
 
@@ -516,6 +540,7 @@
 		gdk_event->crossing.y      = gnome_event->_u.crossing.y;
 		gdk_event->crossing.x_root = gnome_event->_u.crossing.x_root;
 		gdk_event->crossing.y_root = gnome_event->_u.crossing.y_root;
+		gdk_event->crossing.state  = gnome_event->_u.crossing.state;
 		switch (gnome_event->_u.crossing.mode){
 		case Bonobo_Gdk_NORMAL:
 			gdk_event->crossing.mode = GDK_CROSSING_NORMAL;
@@ -533,11 +558,92 @@
 	g_assert_not_reached ();
 }
 
-static void
-free_event (GdkEvent *event)
+/**
+ * handle_event:
+ * @canvas: the pseudo-canvas that this component is part of.
+ * @ev: The GdkEvent event as set up for the component.
+ *
+ * Returns: True if a canvas item handles the event and returns true.
+ *
+ * Passes the remote item's event back into the local pseudo-canvas so
that
+ * canvas items can see events the normal way as if they were not using
bonobo.
+ */
+static gboolean 
+handle_event(GtkWidget *canvas, GdkEvent *ev)
 {
-	if (event->type == GDK_KEY_RELEASE || event->type == GDK_KEY_PRESS)
-		g_free (event->key.string);
+        GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS(canvas);
+        gboolean retval = FALSE;
+
+        switch (ev->type) {
+                case GDK_ENTER_NOTIFY:
+                       
gnome_canvas_world_to_window(GNOME_CANVAS(canvas),
+                                        ev->crossing.x, ev->crossing.y,
+                                        &ev->crossing.x,
&ev->crossing.y);
+                        retval = (klass->enter_notify_event)(canvas, 
+                                        &ev->crossing);
+                        break;
+                case GDK_LEAVE_NOTIFY:
+                       
gnome_canvas_world_to_window(GNOME_CANVAS(canvas),
+                                        ev->crossing.x, ev->crossing.y,
+                                        &ev->crossing.x,
&ev->crossing.y);
+                        retval = (klass->leave_notify_event)(canvas, 
+                                        &ev->crossing);
+                        break;
+                case GDK_MOTION_NOTIFY:
+                       
gnome_canvas_world_to_window(GNOME_CANVAS(canvas),
+                                        ev->motion.x, ev->motion.y,
+                                        &ev->motion.x, &ev->motion.y);
+                        retval = (klass->motion_notify_event)(canvas, 
+                                        &ev->motion);
+                        break;
+                case GDK_BUTTON_PRESS:
+                case GDK_2BUTTON_PRESS:
+                case GDK_3BUTTON_PRESS:
+                       
gnome_canvas_world_to_window(GNOME_CANVAS(canvas),
+                                        ev->button.x, ev->button.y,
+                                        &ev->button.x, &ev->button.y);
+                        retval = (klass->button_press_event)(canvas, 
+                                        &ev->button);
+                        break;
+                case GDK_BUTTON_RELEASE:
+                       
gnome_canvas_world_to_window(GNOME_CANVAS(canvas),
+                                        ev->button.x, ev->button.y,
+                                        &ev->button.x, &ev->button.y);
+                        retval = (klass->button_release_event)(canvas, 
+                                        &ev->button);
+                        break;
+                case GDK_KEY_PRESS:
+                        retval = (klass->key_press_event)(canvas,
&ev->key);
+                        break;
+                case GDK_KEY_RELEASE:
+                        retval = (klass->key_release_event)(canvas,
&ev->key);
+                        break;
+                case GDK_FOCUS_CHANGE:
+                        if (&ev->focus_change.in)
+                                retval =
(klass->focus_in_event)(canvas,
+                                        &ev->focus_change);
+                        else
+                                retval =
(klass->focus_out_event)(canvas,
+                                        &ev->focus_change);
+                        break;
+                default:
+                        g_warning("Canvas event not handled %d",
ev->type);
+                        break;
+
+        }
+        return retval;
+}
+
+static gboolean
+handle_event_later (EmitLater *data)
+{
+        GtkWidget *canvas = GTK_WIDGET(data->arg1);
+        GdkEvent *event = (GdkEvent *)data->arg2;
+
+        handle_event(canvas, event);
+        gdk_event_free(event);
+        g_free(data);
+        return FALSE;
 }
 
 /*
@@ -552,21 +658,42 @@
 {
 	Gcc *gcc = GCC (bonobo_object_from_servant (servant));
 	GnomeCanvasItem *item = GNOME_CANVAS_ITEM (gcc->priv->item);
-	GdkEvent gdk_event;
-	int retval;
-
-	Bonobo_Gdk_Event_to_GdkEvent (gnome_event, &gdk_event);
+	GdkEvent *gdk_event = gdk_event_new(GDK_NOTHING);
+	CORBA_boolean retval = FALSE;
+        EmitLater *data;
 
 	restore_state (item, state);
-
-	g_signal_emit_by_name (gcc, "event", &gdk_event);
-
-	if (ICLASS (item)->event)
-		retval = ICLASS (item)->event (item, &gdk_event);
-	else
-		retval = FALSE;
-
-	free_event (&gdk_event);
+        
+        gdk_event->any.window = item->canvas->layout.bin_window;
+        g_object_ref(gdk_event->any.window);
+
+	Bonobo_Gdk_Event_to_GdkEvent (gnome_event, gdk_event);
+
+        /*
+         * Problem: When dealing with multiple canvas component's
within the
+         * same process it is possible to get to this point when one of
the
+         * pseudo-canvas's is inside its idle loop.  This is normally
not a
+         * problem unless an event from one component can trigger a
request for
+         * an update on another component.
+         *
+         * Solution: If any component is in do_update, set up an
idle_handler
+         * and send the event later. If the event is sent later, the
client will
+         * get a false return value.  Normally this value is used to
determine
+         * whether or not to propagate the event up the canvas group
tree.
+         */
+
+        if (!do_update_flag) {
+                retval = handle_event(GTK_WIDGET(item->canvas),
gdk_event);
+                gdk_event_free(gdk_event);
+        }
+        else {
+                data = g_new0(EmitLater, 1);
+                data->arg1 = (gpointer)item->canvas;
+                data->arg2 = (gpointer)gdk_event;
+                /* has a higher priority then do_update*/
+                g_idle_add_full(GDK_PRIORITY_REDRAW-10,
+                                (GSourceFunc)handle_event_later, data,
NULL);
+        }
 
 	return retval;
 }
@@ -592,13 +719,37 @@
 }
 
 static void
+set_bounds_later(EmitLater *data)
+{
+        CORBA_Environment ev;
+
+        CORBA_exception_init (&ev);
+
+        g_signal_emit(GCC(data->arg1), gcc_signals [SET_BOUNDS], 0,
(const
+                                Bonobo_Canvas_DRect *) data->arg2,
&ev);
+
+        g_free(data);
+        CORBA_exception_free(&ev);
+}
+
+static void
 impl_Bonobo_Canvas_Component_setBounds (PortableServer_Servant    
servant,
 					const Bonobo_Canvas_DRect *bbox,
 					CORBA_Environment         *ev)
 {
 	Gcc *gcc = GCC (bonobo_object_from_servant (servant));
+        EmitLater *data;
 
-	g_signal_emit (gcc, gcc_signals [SET_BOUNDS], 0, bbox, &ev);
+        if (!do_update_flag) {
+                g_signal_emit (gcc, gcc_signals [SET_BOUNDS], 0, bbox,
&ev);
+        }
+        else {
+                data = g_new0(EmitLater, 1);
+                data->arg1 = (gpointer)gcc;
+                data->arg2 = (gpointer)bbox;
+                g_idle_add_full(GDK_PRIORITY_REDRAW-10,
+                                (GSourceFunc)set_bounds_later, data,
NULL);
+        }
 }
 
 static void
@@ -809,23 +960,21 @@
 {
 	RootItemHack *rih = (RootItemHack *) item;
 	CORBA_Environment ev;
-	GnomeCanvasItemClass *gci_class = gtk_type_class (
-					gnome_canvas_item_get_type ());
 
 	CORBA_exception_init (&ev);
-	Bonobo_Canvas_ComponentProxy_requestUpdate (rih->proxy, &ev);
-	CORBA_exception_free (&ev);
 
-	/*
-	 * Mark our canvas and item as fully updated
-	 */
+        /* If we get here then we know the GnomeCanvas must be inside
+         * do_update. The flag tells ALL components not to send events
that
+         * might trigger another update request and thereby cause the
canvas
+         * NEED_UPDATE flags to become unsyncronized.
+         */
+        do_update_flag = TRUE;
 
-	(* gci_class->update) (item, affine, svp, flags);
+	Bonobo_Canvas_ComponentProxy_requestUpdate (rih->proxy, &ev);
 
-	if (item->canvas->redraw_area)
-		art_uta_free (item->canvas->redraw_area);
-	item->canvas->redraw_area = NULL;
-	item->canvas->need_redraw = FALSE;
+        do_update_flag = FALSE;
+
+	CORBA_exception_free (&ev);
 }
 
 static void
@@ -898,8 +1047,12 @@
 
 	canvas->root = GNOME_CANVAS_ITEM (root_item_hack_new (canvas, proxy));
 
+        /* A hack to prevent gtkwidget from issuing a warning about
there not
+           being a parent class. */
+        gtk_container_add(GTK_CONTAINER
(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
+                            GTK_WIDGET(canvas));
 	gtk_widget_realize (GTK_WIDGET (canvas));
-	
+
 	/* Gross */
 	GTK_WIDGET_SET_FLAGS (canvas, GTK_VISIBLE | GTK_MAPPED);
 
@@ -990,3 +1143,103 @@
 	return corba_uic;
 }
 
+/* BonoboCanvasComponentFactory is used to replace the old
BonoboEmbeddable
+ * object.  It sets up a canvas component factory to conform with the
current
+ * Bonobo IDL.
+ */
+
+#define BONOBO_CANVAS_COMPONENT_FACTORY_TYPE       \
+   (bonobo_canvas_component_factory_get_type())
+
+#define BONOBO_CANVAS_COMPONENT_FACTORY(o)    \
+   (G_TYPE_CHECK_INSTANCE_CAST ((o),\
+   BONOBO_CANVAS_COMPONENT_FACTORY_TYPE, BonoboCanvasComponentFactory))
+
+typedef struct _BonoboCanvasComponentFactoryPrivate \
+   BonoboCanvasComponentFactoryPrivate;
+
+typedef struct {
+        BonoboObject base;
+        BonoboCanvasComponentFactoryPrivate *priv;
+} BonoboCanvasComponentFactory;
+
+typedef struct {
+        BonoboObjectClass parent_class;
+
+        POA_Bonobo_CanvasComponentFactory__epv epv;
+} BonoboCanvasComponentFactoryClass;
+       
+GType bonobo_canvas_component_factory_get_type(void) G_GNUC_CONST;
+
+struct _BonoboCanvasComponentFactoryPrivate {
+   GnomeItemCreator item_creator;
+   void *item_creator_data;
+};
+
+static GObjectClass *gccf_parent_class;
+
+static Bonobo_Canvas_Component
+impl_Bonobo_canvas_component_factory_createCanvasItem (
+   PortableServer_Servant servant, CORBA_boolean aa,
+   const Bonobo_Canvas_ComponentProxy _item_proxy,
+   CORBA_Environment *ev)
+{
+        BonoboCanvasComponentFactory *factory =
BONOBO_CANVAS_COMPONENT_FACTORY(
+              bonobo_object_from_servant (servant));
+        Bonobo_Canvas_ComponentProxy item_proxy;
+        BonoboCanvasComponent *component;
+        GnomeCanvas *pseudo_canvas;
+
+        if (factory->priv->item_creator == NULL)
+                return CORBA_OBJECT_NIL;
+
+        item_proxy = CORBA_Object_duplicate (_item_proxy, ev);
+
+	pseudo_canvas = bonobo_canvas_new (aa, item_proxy);
+
+        component = (*factory->priv->item_creator)(
+                /*factory,*/ pseudo_canvas,
factory->priv->item_creator_data);
+
+        return bonobo_object_dup_ref (BONOBO_OBJREF (component), ev);
+}
+
+static void
+bonobo_canvas_component_factory_class_init (
+      BonoboCanvasComponentFactoryClass *klass)
+{
+        POA_Bonobo_CanvasComponentFactory__epv *epv = &klass->epv;
+
+        gccf_parent_class = g_type_class_peek_parent(klass);
+        epv->createCanvasComponent = 
+           impl_Bonobo_canvas_component_factory_createCanvasItem;
+}
+
+static void
+bonobo_canvas_component_factory_init (BonoboCanvasComponentFactory
*factory)
+{
+        factory->priv = g_new0 (BonoboCanvasComponentFactoryPrivate,
1);
+}
+
+BONOBO_TYPE_FUNC_FULL (BonoboCanvasComponentFactory,
+                       Bonobo_CanvasComponentFactory,
+                       BONOBO_TYPE_X_OBJECT,
+                       bonobo_canvas_component_factory);
+
+/**
+ * bonobo_canvas_component_factory_new:
+ * @item_factory: A callback invoke when the container activates the
object.
+ * @user_data: User data pointer.
+ *
+ * Returns: The object to be passed into bonobo_generic_factory_main.
+ */
+BonoboObject *bonobo_canvas_component_factory_new(
+      GnomeItemCreator item_factory, void *user_data)
+{
+        BonoboCanvasComponentFactory *factory;
+        factory = g_object_new (BONOBO_CANVAS_COMPONENT_FACTORY_TYPE,
NULL);
+
+        factory->priv->item_creator = item_factory;
+        factory->priv->item_creator_data = user_data;
+
+        return BONOBO_OBJECT(factory); 
+}


=============================================================================
--- bonobo-canvas-item.c.orig	Tue Feb 12 06:09:17 2002
+++ bonobo-canvas-item.c	Mon May  5 20:28:09 2003
@@ -192,6 +192,7 @@
 
 	CORBA_exception_init (&ev);
 	prepare_state (item, &state);
+
 	cuta = Bonobo_Canvas_Component_update (
 		gbi->priv->object,
 		&state, affine, clip_path, item_flags,
@@ -200,6 +201,7 @@
 
 	if (!BONOBO_EX (&ev)){
 		if (cuta->width > 0 && cuta->height > 0){
+
 			ArtUta *uta;
 
 			uta = uta_from_cuta (cuta);
@@ -250,6 +252,11 @@
 		gbi->priv->realize_pending = 1;
 		return;
 	}
+
+        proxy_size_allocate (
+                item->canvas,
+                &(GTK_WIDGET (item->canvas)->allocation),
+                BONOBO_CANVAS_ITEM(item));
 		
 	g_signal_connect (item->canvas, "size_allocate",
 			  G_CALLBACK (proxy_size_allocate), item);
@@ -447,7 +454,7 @@
 		e->_d = Bonobo_Gdk_MOTION;
 		e->_u.motion.time = event->motion.time;
 		e->_u.motion.x = event->motion.x;
-		e->_u.motion.y = event->motion.x;
+		e->_u.motion.y = event->motion.y;
 		e->_u.motion.x_root = event->motion.x_root;
 		e->_u.motion.y_root = event->motion.y_root;
 #ifdef FIXME
@@ -491,6 +498,7 @@
 		e->_u.crossing.y = event->crossing.y;
 		e->_u.crossing.x_root = event->crossing.x_root;
 		e->_u.crossing.y_root = event->crossing.y_root;
+		e->_u.crossing.state = event->crossing.state;
 
 		switch (event->crossing.mode){
 		case GDK_CROSSING_NORMAL:
@@ -556,7 +564,11 @@
 
 		gbi->priv->object = bonobo_object_release_unref (gbi->priv->object,
&ev);
 
-		factory = bonobo_value_get_corba_object (value);
+                /* FIXME: I can't make it work as corba_object. 
+                   Using bonobo_unknown for now. */
+		/* factory = bonobo_value_get_corba_object (value); */
+               
+		factory = bonobo_value_get_unknown (value);
 
 		g_return_if_fail (factory != CORBA_OBJECT_NIL);
 
@@ -580,12 +592,6 @@
 			return;
 		}
 
-		/* Initial size notification */
-		proxy_size_allocate (
-			GNOME_CANVAS_ITEM (gbi)->canvas,
-			&(GTK_WIDGET (GNOME_CANVAS_ITEM (gbi)->canvas)->allocation),
-			gbi);
-	
 		if (gbi->priv->realize_pending){
 			gbi->priv->realize_pending = 0;
 			gbi_realize (GNOME_CANVAS_ITEM (gbi));
@@ -639,6 +645,8 @@
 	GnomeCanvasItemClass *item_class =
 		(GnomeCanvasItemClass *) object_class;
 
+	gobject_class->set_property = gbi_set_property;
+
 	g_object_class_install_property (
 		gobject_class,
 		PROP_CORBA_FACTORY,
@@ -660,7 +668,6 @@
 			G_PARAM_WRITABLE));
 	
 	gobject_class->finalize     = gbi_finalize;
-	gobject_class->set_property = gbi_set_property;
 
 	item_class->update     = gbi_update;
 	item_class->realize    = gbi_realize;
@@ -672,13 +679,42 @@
 	item_class->event      = gbi_event;
 }
 
+static gboolean
+gbi_idle_handler (GnomeCanvasItem *item)
+{
+	gnome_canvas_item_request_update (item);
+        return FALSE;
+}
+
 static void
 impl_Bonobo_Canvas_ComponentProxy_requestUpdate (PortableServer_Servant
servant,
 					         CORBA_Environment     *ev)
 {
 	ComponentProxyServant *item_proxy = (ComponentProxyServant *) servant;
 
-	gnome_canvas_item_request_update (item_proxy->item_bound);
+        if (item_proxy->item_bound->canvas->idle_id == 0)
+        {
+        	gnome_canvas_item_request_update (item_proxy->item_bound);
+        }
+        else
+        {
+                /* Problem: It is possible to get here at a time when
the canvas
+                 * is in the middle of a do_update.  This happens
because
+                 * this proxy call might be waiting in the queue when
+                 * the this object calls
Bonobo_Canvas_Component_update.
+                 *
+                 * Solution:
+                 * The canvas is either in its do_update routine or it
is
+                 * waiting to do an update.  If it is waiting this
idle_handler
+                 * will get called just before the canvas's handler. 
If it is
+                 * in the middle of a do_update, then this will queue
for the
+                 * next one.
+                 */
+
+                 g_idle_add_full(GDK_PRIORITY_REDRAW-6,
+                                 (GSourceFunc)gbi_idle_handler, 
+                                 item_proxy->item_bound, NULL);
+        }
 
 }
 					    
@@ -719,10 +755,12 @@
 	return bonobo_object_dup_ref (item_proxy->ui_container, NULL);
 }
 
+static PortableServer_ServantBase__epv item_proxy_base_epv;
+
 static POA_Bonobo_Canvas_ComponentProxy__epv item_proxy_epv;
 
 static POA_Bonobo_Canvas_ComponentProxy__vepv item_proxy_vepv = {
-	NULL,
+	&item_proxy_base_epv,
 	&item_proxy_epv
 };
 
@@ -736,6 +774,8 @@
 	ComponentProxyServant *item_proxy = g_new0 (ComponentProxyServant, 1);
 	CORBA_Environment ev;
 	
+        item_proxy->proxy_servant.vepv = &item_proxy_vepv;
+
 	CORBA_exception_init (&ev);
 	POA_Bonobo_Canvas_ComponentProxy__init ((PortableServer_Servant)
item_proxy, &ev);
 
@@ -744,7 +784,6 @@
 	item_proxy_epv.ungrabFocus    =
impl_Bonobo_Canvas_ComponentProxy_ungrabFocus;
 	item_proxy_epv.getUIContainer =
impl_Bonobo_Canvas_ComponentProxy_getUIContainer;
 
-	item_proxy->proxy_servant.vepv = &item_proxy_vepv;
 	item_proxy->item_bound = item;
 
 	item_proxy->oid = PortableServer_POA_activate_object (






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