Sensitivity patches



Here is the updated version of the sensitivity patch, this time working
completely, and for the enjoyment of the entire components list.

Also attached is some ugly sample code and a Makefile which shows the
bug.

OK, so what's wrong?  If you do _set_sensitive to insensitize a control, it
is likely to stay insensitive for all eternity.  The problem?  It doesn't
proxy the state correctly.  It just does gtk_widget_set_state, which in
fact does some BAD things.  If you do
gtk_widget_set_state (w, GTK_STATE_INSENSITIVE), it will be the same
as _set_sensitive with FALSE.  HOWEVER, returning to another state with
the same function will NOT do the trick of _set_sensitive with TRUE,
thus the widget stays insensitive.  Since there is no separate interface
in controls for sensitivity, we must work within just this one bit of
information.

Here are the four cases

1) Out of process, control initially sensitive
   Current behaviour:  Initially sensitive, if you _set_sensitive
   with FALSE, and then _set_sensitive with TRUE, it will stay 
   insensitive
2) Out of process, control initially insensitive
   Current behaviour:  Initially insensitive, no way to make it
   sensitive
3) In process, control initially sensitive
   Current behaviour:  The only one working, this is because, the
   CORBA setState method NEVER gets used and the state is proxied
   by normal GTK+ methods
4) In process, control initially insensitive
   Current behaviour:  Initially insensitive, no way to make it
   sensitive

So currently we have 1 out of 4, and worst of all the bug makes
the control unusable.

So what does the patch do:

1) When setState gets an _INSENSITIVE state, it does _set_sensitive
   with FALSE.  If it gets another state and the control widget
   is currently insensitive, it does _set_sensitive with TRUE.
2) The proxying of the state with the setState method is moved from
   the socket to the container, so that it works in both local and
   remote cases.

Why the second part of the patch you ask?  Look at case number 4 above.
Because the set_sensitive is done before the control is realized,
it is done before the control frame knows this is a local widget and
thus does the setState, which makes the control widget insensitive.
Later when it would get added into GTK+ hierarchy, it would not get
sensitized because you call _set_sensitive on the frame not the
control.  So if we do proxying in both the local and remote cases,
everything works.

George

-- 
George <jirka 5z com>
   I either want less corruption, or more chance to participate in it.
                       -- Ashleigh Brilliant
Index: bonobo/bonobo-control-frame.c
===================================================================
RCS file: /cvs/gnome/bonobo/bonobo/bonobo-control-frame.c,v
retrieving revision 1.61
diff -u -p -r1.61 bonobo-control-frame.c
--- bonobo/bonobo-control-frame.c	2001/04/12 16:32:55	1.61
+++ bonobo/bonobo-control-frame.c	2001/04/19 02:20:01
@@ -144,7 +144,7 @@ bonobo_control_frame_autoactivate_focus_
 
 
 static void
-bonobo_control_frame_socket_state_changed (GtkWidget    *socket,
+bonobo_control_frame_socket_state_changed (GtkWidget    *container,
 					   GtkStateType  previous_state,
 					   gpointer      user_data)
 {
@@ -155,7 +155,7 @@ bonobo_control_frame_socket_state_change
 
 	bonobo_control_frame_control_set_state (
 		control_frame,
-		GTK_WIDGET_STATE (control_frame->priv->socket));
+		GTK_WIDGET_STATE (control_frame->priv->container));
 }
 
 
@@ -234,14 +234,6 @@ bonobo_control_frame_create_socket (Bono
 			    control_frame);
 
 	/*
-	 * Setup a handler to proxy state changes.
-	 */
-	gtk_signal_connect (GTK_OBJECT (control_frame->priv->socket),
-			    "state_changed",
-			    bonobo_control_frame_socket_state_changed,
-			    control_frame);
-
-	/*
 	 * Setup a handler for socket destroy.
 	 */
 	gtk_signal_connect (GTK_OBJECT (control_frame->priv->socket),
@@ -303,6 +295,15 @@ bonobo_control_frame_construct (BonoboCo
 	gtk_widget_ref (control_frame->priv->container);
 	gtk_object_sink (GTK_OBJECT (control_frame->priv->container));
 	gtk_widget_show (control_frame->priv->container);
+
+	/*
+	 * Setup a handler to proxy state from the container.
+	 */
+	gtk_signal_connect (GTK_OBJECT (control_frame->priv->container),
+			    "state_changed",
+			    bonobo_control_frame_socket_state_changed,
+			    control_frame);
+
 
 	bonobo_control_frame_create_socket (control_frame);
 
Index: bonobo/bonobo-control.c
===================================================================
RCS file: /cvs/gnome/bonobo/bonobo/bonobo-control.c,v
retrieving revision 1.75
diff -u -p -r1.75 bonobo-control.c
--- bonobo/bonobo-control.c	2001/04/12 16:32:56	1.75
+++ bonobo/bonobo-control.c	2001/04/19 02:20:01
@@ -415,12 +415,20 @@ impl_Bonobo_Control_setState (PortableSe
 			       CORBA_Environment          *ev)
 {
 	BonoboControl *control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
+	GtkStateType gtk_state = bonobo_control_gtk_state_from_corba (state);
 
 	g_return_if_fail (control->priv->widget != NULL);
 
-	gtk_widget_set_state (
-		control->priv->widget,
-		bonobo_control_gtk_state_from_corba (state));
+	if (gtk_state == GTK_STATE_INSENSITIVE) {
+		gtk_widget_set_sensitive (control->priv->widget, FALSE);
+	} else {
+		if (! GTK_WIDGET_SENSITIVE (control->priv->widget)) {
+			gtk_widget_set_sensitive (control->priv->widget, TRUE);
+		}
+
+		gtk_widget_set_state (control->priv->widget,
+				      gtk_state);
+	}
 }
 
 static Bonobo_PropertyBag
/*
 * Sensitivity showing hack, ugly code
 *  -George
 *
 * Used to be:
 *
 * sample-control-container.c
 * 
 * Authors:
 *   Nat Friedman  (nat helixcode com)
 *   Michael Meeks (michael helixcode com)
 *
 * Copyright 1999, 2000 Helix Code, Inc.
 */
#include <gnome.h>
#include <liboaf/liboaf.h>
#include <bonobo.h>


static void
app_destroy_cb (GtkWidget *app, BonoboUIContainer *uic)
{
	gtk_exit (0);
}

static void
toggle_sensitive (GtkWidget *w, GtkWidget *control)
{
	if (GTK_WIDGET_SENSITIVE (control))
		gtk_widget_set_sensitive (control, FALSE);
	else
		gtk_widget_set_sensitive (control, TRUE);
}

static GtkWidget *
make_inprocess_control (BonoboUIContainer *uic)
{
	BonoboControl *control;
	GtkWidget *controlw;
	GtkWidget *w = gtk_label_new (">>> this is a control <<<");
	gtk_widget_show (w);

	control = bonobo_control_new (w);

	controlw = bonobo_widget_new_control_from_objref
		(BONOBO_OBJREF (control), BONOBO_OBJREF (uic));
	
	return controlw;
}


static guint
container_create (void)
{
	GtkWidget       *control;
	GtkWidget       *box;
	BonoboUIContainer *uic;
	GtkWindow       *window;
	GtkWidget       *app;

	app = bonobo_window_new ("sample-control-container",
				 "Sample Bonobo Control Container");

	window = GTK_WINDOW (app);
	
	uic = bonobo_ui_container_new ();

	bonobo_ui_container_set_win (uic, BONOBO_WINDOW (app));

	gtk_window_set_default_size (window, 500, 440);
	gtk_window_set_policy (window, TRUE, TRUE, FALSE);

	gtk_signal_connect (GTK_OBJECT (window), "destroy",
			    GTK_SIGNAL_FUNC (app_destroy_cb), uic);

	box = gtk_vbox_new (FALSE, 5);
	bonobo_window_set_contents (BONOBO_WINDOW (app), box);

	control = bonobo_widget_new_control ("OAFIID:Bonobo_Sample_Clock",
					     BONOBO_OBJREF (uic));

	if (control) {
		GtkWidget *w;

		gtk_widget_set_sensitive (GTK_WIDGET (control), FALSE);
		
		gtk_box_pack_start (GTK_BOX (box), 
				    gtk_label_new ("Initially insensitive:"),
				    FALSE, FALSE, 0);
		gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
		w = gtk_button_new_with_label ("toggle_sensitivity");
		gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
		gtk_signal_connect (GTK_OBJECT (w), "clicked",
				    GTK_SIGNAL_FUNC (toggle_sensitive),
				    control);
	}

	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);

	control = bonobo_widget_new_control ("OAFIID:Bonobo_Sample_Clock",
					     BONOBO_OBJREF (uic));

	if (control) {
		GtkWidget *w;

		gtk_box_pack_start (GTK_BOX (box), 
				    gtk_label_new ("Initially sensitive:"),
				    FALSE, FALSE, 0);
		gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
		w = gtk_button_new_with_label ("toggle_sensitivity");
		gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
		gtk_signal_connect (GTK_OBJECT (w), "clicked",
				    GTK_SIGNAL_FUNC (toggle_sensitive),
				    control);
	}

	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);


	control = make_inprocess_control (uic);

	if (control) {
		GtkWidget *w;

		gtk_widget_set_sensitive (GTK_WIDGET (control), FALSE);
		
		gtk_box_pack_start (GTK_BOX (box), 
				    gtk_label_new ("inprocess initially insensitive:"),
				    FALSE, FALSE, 0);
		gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
		w = gtk_button_new_with_label ("toggle_sensitivity");
		gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
		gtk_signal_connect (GTK_OBJECT (w), "clicked",
				    GTK_SIGNAL_FUNC (toggle_sensitive),
				    control);
	}

	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (box), 
			    gtk_hseparator_new (),
			    FALSE, FALSE, 0);

	control = make_inprocess_control (uic);

	if (control) {
		GtkWidget *w;

		gtk_box_pack_start (GTK_BOX (box), 
				    gtk_label_new ("inprocess initially sensitive:"),
				    FALSE, FALSE, 0);
		gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
		w = gtk_button_new_with_label ("toggle_sensitivity");
		gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
		gtk_signal_connect (GTK_OBJECT (w), "clicked",
				    GTK_SIGNAL_FUNC (toggle_sensitive),
				    control);
	}

	gtk_widget_show_all (GTK_WIDGET (window));

	return FALSE;
}

int
main (int argc, char **argv)
{
	CORBA_Environment ev;
	CORBA_ORB orb;
	CORBA_exception_init (&ev);

	/* Encorage -lefence to play ball */
	{ char *tmp = malloc (4); if (tmp) free (tmp); }

        gnome_init_with_popt_table ("sample-control-container", "0.0",
				    argc, argv,
				    oaf_popt_options, 0, NULL); 
	orb = oaf_init (argc, argv);

	if (bonobo_init (orb, NULL, NULL) == FALSE)
		g_error ("Could not initialize Bonobo");

	/*
	 * We can't make any CORBA calls unless we're in the main
	 * loop.  So we delay creating the container here.
	 */
	gtk_idle_add ((GtkFunction) container_create, NULL);

	bonobo_main ();

	return 0;
}
CFLAGS=-g -Wall `gnome-config --cflags bonobox`
LDFLAGS=-g -Wall `gnome-config --libs bonobox`

all: sensitivity


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