empathy r2796 - trunk/libempathy-gtk



Author: xclaesse
Date: Fri Apr 10 16:54:49 2009
New Revision: 2796
URL: http://svn.gnome.org/viewvc/empathy?rev=2796&view=rev

Log:
Fix focus-out autocommit using an idle handler

From: Davyd Madeley <davyd madeley id au>

Modified:
   trunk/libempathy-gtk/empathy-presence-chooser.c

Modified: trunk/libempathy-gtk/empathy-presence-chooser.c
==============================================================================
--- trunk/libempathy-gtk/empathy-presence-chooser.c	(original)
+++ trunk/libempathy-gtk/empathy-presence-chooser.c	Fri Apr 10 16:54:49 2009
@@ -59,6 +59,7 @@
 	gboolean     editing_status;
 	int          block_set_editing;
 	int          block_changed;
+	guint        focus_out_idle_source;
 
 	McPresence   state;
 	int          previous_type;
@@ -225,11 +226,20 @@
                                  GParamSpec *pspec,
 				 gpointer user_data)
 {
+	EmpathyPresenceChooserPriv *priv = GET_PRIV (self);
 	gboolean shown;
+
 	g_object_get (self, "popup-shown", &shown, NULL);
 
 	if (!shown) return;
 
+	/* see presence_chooser_entry_focus_out_cb() for what this does */
+	if (priv->focus_out_idle_source != 0)
+	{
+		g_source_remove (priv->focus_out_idle_source);
+		priv->focus_out_idle_source = 0;
+	}
+
 	GtkTreeModel *model = create_model ();
 
 	gtk_combo_box_set_model (GTK_COMBO_BOX (self), GTK_TREE_MODEL (model));
@@ -249,6 +259,7 @@
 	if (editing)
 	{
 		priv->editing_status = TRUE;
+
 		gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
 				GTK_ENTRY_ICON_SECONDARY,
 				GTK_STOCK_OK);
@@ -278,6 +289,15 @@
 			/* unset the focus */
 			gtk_window_set_focus (GTK_WINDOW (window), NULL);
 		}
+
+		/* see presence_chooser_entry_focus_out_cb()
+		 * for what this does */
+		if (priv->focus_out_idle_source != 0)
+		{
+			g_source_remove (priv->focus_out_idle_source);
+			priv->focus_out_idle_source = 0;
+		}
+
 		gtk_editable_set_position (GTK_EDITABLE (entry), 0);
 
 		priv->editing_status = FALSE;
@@ -392,7 +412,7 @@
 
 static void
 presence_chooser_entry_changed_cb (EmpathyPresenceChooser *self,
-				   gpointer user_data)
+				   GtkEntry               *entry)
 {
 	EmpathyPresenceChooserPriv *priv = GET_PRIV (self);
 
@@ -462,12 +482,23 @@
 				icon_name);
 
 		/* preseed the status */
-		if (priv->previous_type == ENTRY_TYPE_BUILTIN)
+		if (priv->editing_status)
+		{
+			/* if the user is already in editing mode and changes
+			 * the status type, preseed the text they've already
+			 * entered */
+			/* FIXME: make this work */
+		}
+		else if (priv->previous_type == ENTRY_TYPE_BUILTIN)
 		{
+			/* if their previous entry was a builtin, don't
+			 * preseed */
 			gtk_entry_set_text (GTK_ENTRY (entry), "");
 		}
 		else
 		{
+			/* else preseed the text of their currently entered
+			 * status message */
 			const char *status = empathy_idle_get_status (priv->idle);
 			gtk_entry_set_text (GTK_ENTRY (entry), status);
 		}
@@ -514,6 +545,19 @@
 }
 
 static gboolean
+presence_chooser_entry_focus_out_idle_cb (gpointer user_data)
+{
+	DEBUG ("Autocommiting status message\n");
+
+	EmpathyPresenceChooser *chooser = EMPATHY_PRESENCE_CHOOSER (user_data);
+	GtkWidget *entry = gtk_bin_get_child (GTK_BIN (chooser));
+
+	presence_chooser_entry_activate_cb (chooser, GTK_ENTRY (entry));
+
+	return FALSE;
+}
+
+static gboolean
 presence_chooser_entry_focus_out_cb (EmpathyPresenceChooser *chooser,
                                      GdkEventFocus *event,
 				     GtkEntry *entry)
@@ -522,9 +566,25 @@
 
 	if (priv->editing_status)
 	{
-		// entry_activate_cb (chooser, entry);
+		/* this seems a bit evil and maybe it will be fragile,
+		 * someone should think of a better way to do it.
+		 *
+		 * The entry has focused out, but we don't know where the focus
+		 * has gone. If it goes to the combo box, we don't want to
+		 * do anything. If it's gone anywhere else, we want to commit
+		 * the result.
+		 *
+		 * Thus we install this idle handler and store its source.
+		 * If the source is scheduled when the popup handler runs,
+		 * it will remove it, else the callback will commit the result.
+		 */
+		priv->focus_out_idle_source = g_idle_add (
+				presence_chooser_entry_focus_out_idle_cb,
+				chooser);
 	}
 
+	gtk_editable_set_position (GTK_EDITABLE (entry), 0);
+
 	return FALSE;
 }
 
@@ -617,6 +677,10 @@
 		g_source_remove (priv->flash_timeout_id);
 	}
 
+	if (priv->focus_out_idle_source) {
+		g_source_remove (priv->focus_out_idle_source);
+	}
+
 	g_signal_handlers_disconnect_by_func (priv->idle,
 					      presence_chooser_presence_changed_cb,
 					      object);



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