[epiphany] downloader-view: stay alive until notifications are gone



commit 5d2c310ba6e13fbfa3cb41c40c9b4b9e387df04e
Author: Diego Escalante Urrelo <descalante igalia com>
Date:   Tue Mar 2 19:15:12 2010 -0500

    downloader-view: stay alive until notifications are gone
    
    When using notifications for downloads we usually hit the ugly case where the
    notification pops but there is no GtkStatusIcon for it so it will pop in the
    default location (usually bottom right). This is inconsistent with the behavior
    when the GtkStatusIcon is present, which is to show it attached to it.
    
    To fix this we hold a reference to the DownloaderView when showing the
    notification and release it when such notification has been closed.
    
    Bug #611779

 embed/downloader-view.c |  134 ++++++++++++++++++++++++-----------------------
 1 files changed, 69 insertions(+), 65 deletions(-)
---
diff --git a/embed/downloader-view.c b/embed/downloader-view.c
index db4e8ee..c5ec5c4 100644
--- a/embed/downloader-view.c
+++ b/embed/downloader-view.c
@@ -71,10 +71,6 @@ struct _DownloaderViewPrivate
 	GtkStatusIcon *status_icon;
 	gboolean ownref;
 
-#ifdef HAVE_LIBNOTIFY
-	NotifyNotification *notification;
-#endif
-
 	guint source_id;
 };
 
@@ -120,11 +116,6 @@ download_dialog_delete_event_cb (GtkWidget *window,
 				 GdkEventAny *event,
 				 DownloaderView *dv);
 
-#ifdef HAVE_LIBNOTIFY
-static void
-show_notification_window (DownloaderView *dv);
-#endif
-
 static void
 download_progress_cb (WebKitDownload *download,
 		      GParamSpec *pspec,
@@ -193,10 +184,6 @@ show_status_icon (DownloaderView *dv)
 
 	priv->status_icon = gtk_status_icon_new_from_stock (STOCK_DOWNLOAD);
 
-#ifdef HAVE_LIBNOTIFY
-	notify_notification_attach_to_status_icon (priv->notification, priv->status_icon);
-#endif
-
 	g_signal_connect_swapped (priv->status_icon, "activate",
 				  G_CALLBACK (show_downloader_cb), dv);
 	g_signal_connect (priv->status_icon, "popup-menu",
@@ -309,6 +296,65 @@ downloader_view_new (void)
 			 			   NULL));
 }
 
+#ifdef HAVE_LIBNOTIFY
+static void
+notification_closed_cb (NotifyNotification *notification,
+			DownloaderView *dv)
+{
+	g_object_unref (dv);
+}
+
+static gboolean
+show_notification_cb (NotifyNotification *notification)
+{
+	DownloaderView *dv;
+	GError *error = NULL;
+
+	dv = g_object_get_data (G_OBJECT (notification), "dv");
+	notify_notification_show (notification, &error);
+
+	if (error)
+	{
+		/* notification_closed_cb () will never be called. */
+		g_warning ("Error showing download notification: %s",
+			   error->message);
+		g_object_unref (dv);
+		g_error_free (error);
+	}
+
+	return FALSE;
+}
+
+static void
+show_notification (DownloaderView *dv, const char *title, const char *msg)
+{
+	NotifyNotification *notification;
+	GtkStatusIcon *status_icon;
+
+	status_icon = dv->priv->status_icon;
+
+	/* We keep the DownloaderView alive until the notification is gone. */
+	g_object_ref (dv);
+
+	notification = notify_notification_new (title, msg,
+						GTK_STOCK_INFO, NULL);
+
+	g_signal_connect_after (notification, "closed",
+				G_CALLBACK (notification_closed_cb), dv);
+	g_object_set_data (G_OBJECT (notification), "dv", dv);
+
+	notify_notification_set_timeout (notification, NOTIFY_EXPIRES_DEFAULT);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+
+	notify_notification_attach_to_status_icon (notification, status_icon);
+
+	/* There are some visual glitches when the notification is shown and
+	 * the GtkStatusIcon is still not visible. To avoid that, we delay the
+	 * popup a bit. */
+	g_timeout_add (500, (GSourceFunc) show_notification_cb, notification);
+}
+#endif
+
 static char *
 format_interval (gdouble interval)
 {
@@ -528,15 +574,8 @@ update_download_row (DownloaderView *dv, WebKitDownload *download)
 		}
 
 #ifdef HAVE_LIBNOTIFY
-		downloaded = g_strdup_printf (_("The file â??%sâ?? has been downloaded."), 
-						name);
-		notify_notification_update (dv->priv->notification,
-			_("Download finished"), 
-			downloaded, 
-			GTK_STOCK_INFO);
-			
-		show_notification_window (dv);
-		
+		downloaded = g_strdup_printf (_("The file â??%sâ?? has been downloaded."), name);
+		show_notification (dv, _("Download finished"), downloaded);
 		g_free (downloaded);
 #endif
 		downloader_view_remove_download (dv, download);
@@ -645,27 +684,6 @@ update_buttons_timeout_cb (DownloaderView *dv)
 	return FALSE;
 }
 
-#ifdef HAVE_LIBNOTIFY
-static void
-show_notification_window (DownloaderView *dv)
-{
-	if (gtk_status_icon_is_embedded (dv->priv->status_icon))
-	{
-		notify_notification_attach_to_status_icon
-						(dv->priv->notification,
-						 dv->priv->status_icon);
-	}
-	else
-	{
-		notify_notification_attach_to_status_icon
-						(dv->priv->notification,
-						 NULL);
-	}
-
-	notify_notification_show (dv->priv->notification, NULL);
-}
-#endif
-
 void
 downloader_view_add_download (DownloaderView *dv,
 			      WebKitDownload *download)
@@ -683,13 +701,9 @@ downloader_view_add_download (DownloaderView *dv,
 #endif
 	gboolean visible = FALSE;
 
-#ifdef HAVE_LIBNOTIFY
-	char *downloading;
-#endif
-
 	/* dv may be unrefed inside update_download_row if the file
 	 * downloaded completely while the user was choosing where to
-	 * put it, so we need to protect it
+	 * put it, so we need to protect it.
 	 */
 	g_object_ref (dv);
 	g_object_ref (download);
@@ -740,19 +754,16 @@ downloader_view_add_download (DownloaderView *dv,
 	
 	if (eel_gconf_get_boolean (CONF_DOWNLOADS_HIDDEN) && !visible)
 	{
-
 #ifdef HAVE_LIBNOTIFY
-		char *name = ephy_download_get_name (download);
-		downloading = g_strdup_printf(_("The file â??%sâ?? has been added to the downloads queue."), 
-						name);
-		g_free (name);
-		notify_notification_update (dv->priv->notification,
-					_("Download started"), 
-					downloading, 
-					GTK_STOCK_INFO);
+		char *name;
+		char *downloading;
+
+		name = ephy_download_get_name (download);
+		downloading = g_strdup_printf(_("The file â??%sâ?? has been added to the downloads queue."), name);
 		
-		show_notification_window (dv);
+		show_notification (dv, _("Download started"), downloading);
 
+		g_free (name);
 		g_free (downloading);
 #endif
 
@@ -941,13 +952,6 @@ downloader_view_build_ui (DownloaderView *dv)
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
 	g_signal_connect (selection, "changed", G_CALLBACK (selection_changed), dv);
-	
-#ifdef HAVE_LIBNOTIFY
-	priv->notification = notify_notification_new (" ", " ", GTK_STOCK_INFO, NULL);
-	notify_notification_set_timeout (priv->notification, NOTIFY_EXPIRES_DEFAULT);
-	notify_notification_set_urgency (priv->notification, NOTIFY_URGENCY_LOW);
-#endif
-
 }
 
 static void



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