[rhythmbox] remove tray icon



commit 05d83f221c672d6f9271c1117c86aae164c79f9c
Author: Jonathan Matthew <jonathan d14n org>
Date:   Mon May 18 12:09:47 2009 +1000

    remove tray icon
    
    This completely removes the tray icon, and adds a few signals to RBShell
    to allow it to be reimplemented as a plugin.
    
    New signals:
    - visibility-changing: emitted before window visibility changes, allows
      plugins to override the change, or to set the initial visibility of
      the window.
    - notify-playing-entry: emitted when a notification popup should be
      displayed for the current playing entry
    - notify-custom: emitted when a custom notification popup should be
      displayed.
---
 bindings/python/rb.defs                           |   14 +-
 data/ui/rhythmbox-ui.xml                          |   16 +-
 doc/reference/rhythmbox-docs.sgml                 |    1 -
 doc/reference/rhythmbox-sections.txt              |   23 -
 doc/reference/rhythmbox.types                     |    2 -
 lib/rb-marshal.list                               |    2 +
 lib/rb-preferences.h                              |    2 -
 plugins/cd-recorder/rb-playlist-source-recorder.c |    2 +-
 shell/Makefile.am                                 |    2 -
 shell/rb-shell.c                                  |  521 ++-----------
 shell/rb-shell.h                                  |   20 +-
 shell/rb-tray-icon.c                              |  852 ---------------------
 shell/rb-tray-icon.h                              |   85 --
 sources/rb-podcast-source.c                       |   24 +-
 sources/rb-streaming-source.c                     |    4 +-
 widgets/Makefile.am                               |    2 -
 widgets/eggtrayicon.c                             |  630 ---------------
 widgets/eggtrayicon.h                             |   99 ---
 widgets/update-from-egg.sh                        |   26 -
 19 files changed, 96 insertions(+), 2231 deletions(-)

diff --git a/bindings/python/rb.defs b/bindings/python/rb.defs
index 20311a8..1a03381 100644
--- a/bindings/python/rb.defs
+++ b/bindings/python/rb.defs
@@ -418,26 +418,26 @@
   )
 )
 
-(define-method hidden_notify
+(define-method notify_custom
   (of-object "RBShell")
-  (c-name "rb_shell_hidden_notify")
+  (c-name "rb_shell_notify_custom")
   (return-type "none")
   (parameters
     '("guint" "timeout")
     '("const-char*" "primary")
-    '("GdkPixbuf*" "pixbuf")
     '("const-char*" "secondary")
+    '("GdkPixbuf*" "pixbuf")
     '("gboolean" "requested")
   )
 )
 
-(define-method notify_playing_entry
+(define-method do_notify
   (of-object "RBShell")
-  (c-name "rb_shell_notify_playing_entry")
-  (return-type "none")
+  (c-name "rb_shell_do_notify")
+  (return-type "gboolean")
   (parameters
-    '("RhythmDBEntry*" "entry")
     '("gboolean" "requested")
+    '("GError**" "error")
   )
 )
 
diff --git a/data/ui/rhythmbox-ui.xml b/data/ui/rhythmbox-ui.xml
index e7a9a74..cc8246b 100644
--- a/data/ui/rhythmbox-ui.xml
+++ b/data/ui/rhythmbox-ui.xml
@@ -21,7 +21,7 @@
       <separator/>
       <menuitem name="MusicPropertiesMenu" action="MusicProperties"/>
       <separator/>
-      <menuitem name="MusicClose" action="MusicClose"/>
+      <placeholder name="PluginWindowPlaceholder" />
       <menuitem name="MusicQuit" action="MusicQuit"/>
     </menu>
 
@@ -112,20 +112,6 @@
     <placeholder name="PluginPlaceholder" />
   </toolbar>
 
-  <popup name="RhythmboxTrayPopup">
-      <menuitem name="PlayTray" action="ControlPlay"/>
-      <separator/>
-      <menuitem name="PreviousTray" action="ControlPrevious"/>
-      <menuitem name="NextTray" action="ControlNext"/>
-      <separator/>
-      <menuitem name="ShowWindowTray" action="TrayShowWindow"/>
-      <menuitem name="ShowNotifications" action="TrayShowNotifications"/>
-      <separator/>
-      <placeholder name="PluginPlaceholder"/>
-      <separator/>
-      <menuitem name="QuitTray" action="MusicQuit"/>
-  </popup>
-
   <popup name="BrowserSourceViewPopup">
     <menuitem name="AddToQueueLibraryPopup" action="AddToQueue"/>
     <menu name="BrowserSourcePopupPlaylistAdd" action="EditPlaylistAdd">
diff --git a/doc/reference/rhythmbox-docs.sgml b/doc/reference/rhythmbox-docs.sgml
index dd0ee8b..81b868d 100644
--- a/doc/reference/rhythmbox-docs.sgml
+++ b/doc/reference/rhythmbox-docs.sgml
@@ -56,7 +56,6 @@
 		<xi:include href="xml/rb-shell.xml"/>
 		<xi:include href="xml/rb-source-header.xml"/>
 		<xi:include href="xml/rb-statusbar.xml"/>
-		<xi:include href="xml/rb-tray-icon.xml"/>
 	</chapter>
 
 	<chapter>  	
diff --git a/doc/reference/rhythmbox-sections.txt b/doc/reference/rhythmbox-sections.txt
index 94e5da8..2f994b2 100644
--- a/doc/reference/rhythmbox-sections.txt
+++ b/doc/reference/rhythmbox-sections.txt
@@ -97,29 +97,6 @@ RBRemovableMediaManagerPrivate
 </SECTION>
 
 <SECTION>
-<FILE>rb-tray-icon</FILE>
-<TITLE>RBTrayIcon</TITLE>
-RBTrayIcon
-RBTrayIconClass
-rb_tray_icon_new
-rb_tray_icon_get_geom
-rb_tray_icon_notify
-rb_tray_icon_cancel_notify
-rb_tray_icon_set_tooltip_primary_text
-rb_tray_icon_set_tooltip_icon
-rb_tray_icon_set_tooltip_secondary_markup
-<SUBSECTION Standard>
-RB_TRAY_ICON
-RB_IS_TRAY_ICON
-RB_TYPE_TRAY_ICON
-rb_tray_icon_get_type
-RB_TRAY_ICON_CLASS
-RB_IS_TRAY_ICON_CLASS
-RB_TRAY_ICON_GET_CLASS
-RBTrayIconPrivate
-</SECTION>
-
-<SECTION>
 <FILE>rb-shell-clipboard</FILE>
 <TITLE>RBShellClipboard</TITLE>
 RBShellClipboard
diff --git a/doc/reference/rhythmbox.types b/doc/reference/rhythmbox.types
index 58630df..665e3e4 100644
--- a/doc/reference/rhythmbox.types
+++ b/doc/reference/rhythmbox.types
@@ -53,7 +53,6 @@
 #include "rb-statusbar.h"
 #include "rb-stock-icons.h"
 #include "rb-streaming-source.h"
-#include "rb-tray-icon.h"
 #include "rb-tree-dnd.h"
 #include "rb-uri-dialog.h"
 #include "rb-util.h"
@@ -116,7 +115,6 @@ rb_static_playlist_source_get_type
 rb_statusbar_get_type
 rb_streaming_source_get_type
 rb_string_value_map_get_type
-rb_tray_icon_get_type
 rb_tree_drag_dest_get_type
 rb_tree_drag_source_get_type
 rb_uri_dialog_get_type
diff --git a/lib/rb-marshal.list b/lib/rb-marshal.list
index c2edac6..17068c4 100644
--- a/lib/rb-marshal.list
+++ b/lib/rb-marshal.list
@@ -1,3 +1,4 @@
+BOOLEAN:BOOLEAN,BOOLEAN
 BOOLEAN:BOOLEAN,BOOLEAN,BOOLEAN
 BOOLEAN:BOXED
 BOOLEAN:POINTER
@@ -39,6 +40,7 @@ VOID:STRING,STRING
 VOID:STRING,STRING,OBJECT
 VOID:STRING,STRING,STRING
 VOID:STRING,STRING,STRING,UINT,BOOLEAN
+VOID:UINT,STRING,STRING,OBJECT,BOOLEAN
 VOID:ULONG,FLOAT
 VOID:OBJECT,BOOLEAN
 VOID:STRING,STRING,POINTER,POINTER
diff --git a/lib/rb-preferences.h b/lib/rb-preferences.h
index 77a5c53..94b8ed9 100644
--- a/lib/rb-preferences.h
+++ b/lib/rb-preferences.h
@@ -50,11 +50,9 @@ G_BEGIN_DECLS
 #define CONF_UI_COLUMNS_SETUP CONF_PREFIX "/ui/rhythmdb_columns_setup"
 #define CONF_UI_TIME_DISPLAY CONF_PREFIX "/ui/time_display"
 #define CONF_UI_BROWSER_VIEWS CONF_PREFIX "/ui/library/browser_views"
-#define CONF_UI_SHOW_NOTIFICATIONS CONF_PREFIX "/ui/show_notifications"
 #define CONF_STATE_PLAY_ORDER	CONF_PREFIX "/state/play_order"
 #define CONF_STATE_VOLUME	CONF_PREFIX "/state/volume"
 #define CONF_STATE_BURN_DEVICE	CONF_PREFIX "/state/burn_device"
-#define CONF_STATE_WINDOW_VISIBLE	CONF_PREFIX "/state/window_visible"
 #define CONF_UI_AUTO_PROXY_COMPLAINT	CONF_PREFIX "/ui/auto_proxy_complaint"
 
 #define CONF_AUDIOSCROBBLER_USERNAME CONF_PREFIX "/audioscrobbler/username"
diff --git a/plugins/cd-recorder/rb-playlist-source-recorder.c b/plugins/cd-recorder/rb-playlist-source-recorder.c
index 3308ae3..c7f3150 100644
--- a/plugins/cd-recorder/rb-playlist-source-recorder.c
+++ b/plugins/cd-recorder/rb-playlist-source-recorder.c
@@ -559,7 +559,7 @@ burn_cd (RBPlaylistSourceRecorder *source,
 									GTK_ICON_SIZE_BUTTON,
 									NULL);
 		}
-                rb_shell_hidden_notify (source->priv->shell, 0, finished_msg, source->priv->cd_icon, "", FALSE);
+                rb_shell_notify_custom (source->priv->shell, 0, finished_msg, "", source->priv->cd_icon, FALSE);
 
                 /* save the write speed that was used */
                 eel_gconf_set_integer (CONF_STATE_BURN_SPEED, speed);
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 757a113..0e1f98f 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -88,8 +88,6 @@ librbshell_la_SOURCES =              			\
 	rb-play-order-random-by-age-and-rating.h	\
 	rb-play-order-random-by-rating.c		\
 	rb-play-order-random-by-rating.h		\
-	rb-tray-icon.c					\
-	rb-tray-icon.h					\
 	rb-missing-plugins.c				\
 	rb-missing-plugins.h
 
diff --git a/shell/rb-shell.c b/shell/rb-shell.c
index e7facd3..2d2c23c 100644
--- a/shell/rb-shell.c
+++ b/shell/rb-shell.c
@@ -41,8 +41,6 @@
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 
-#include <X11/Xatom.h>
-
 #ifdef HAVE_MMKEYS
 #include <X11/XF86keysym.h>
 #endif /* HAVE_MMKEYS */
@@ -69,7 +67,6 @@
 #include "rb-shell-clipboard.h"
 #include "rb-shell-player.h"
 #include "rb-source-header.h"
-#include "rb-tray-icon.h"
 #include "rb-statusbar.h"
 #include "rb-shell-preferences.h"
 #include "rb-library-source.h"
@@ -132,9 +129,6 @@ static void source_selected_cb (RBSourceList *sourcelist,
 static void rb_shell_playing_source_changed_cb (RBShellPlayer *player,
 						RBSource *source,
 						RBShell *shell);
-static void rb_shell_playing_entry_changed_cb (RBShellPlayer *player,
-					       RhythmDBEntry *entry,
-					       RBShell *shell);
 static void rb_shell_playing_from_queue_cb (RBShellPlayer *player,
 					    GParamSpec *arg,
 					    RBShell *shell);
@@ -149,11 +143,6 @@ static void rb_shell_db_save_error_cb (RhythmDB *db,
 static void rb_shell_db_entry_added_cb (RhythmDB *db,
 					RhythmDBEntry *entry,
 					RBShell *shell);
-static void rb_shell_db_metadata_art_cb (RhythmDB *db,
-					 RhythmDBEntry *entry,
-					 const char *field,
-					 GValue *metadata,
-					 RBShell *shell);
 
 static void rb_shell_playlist_added_cb (RBPlaylistManager *mgr, RBSource *source, RBShell *shell);
 static void rb_shell_playlist_created_cb (RBPlaylistManager *mgr, RBSource *source, RBShell *shell);
@@ -165,19 +154,13 @@ static void rb_shell_transfer_progress_cb (RBRemovableMediaManager *mgr,
 					   RBShell *shell);
 static void rb_shell_source_deleted_cb (RBSource *source, RBShell *shell);
 static void rb_shell_set_window_title (RBShell *shell, const char *window_title);
-static void rb_shell_update_tray_tooltip_elapsed (RBShell *shell);
 static void rb_shell_player_window_title_changed_cb (RBShellPlayer *player,
 					             const char *window_title,
 					             RBShell *shell);
-static void rb_shell_player_elapsed_changed_cb (RBShellPlayer *player,
-						guint elapsed,
-						RBShell *shell);
 static void rb_shell_cmd_about (GtkAction *action,
 		                RBShell *shell);
 static void rb_shell_cmd_contents (GtkAction *action,
 				   RBShell *shell);
-static void rb_shell_cmd_toggle_visibility (GtkAction *action,
-					    RBShell *shell);
 static void rb_shell_cmd_quit (GtkAction *action,
 			       RBShell *shell);
 static void rb_shell_cmd_preferences (GtkAction *action,
@@ -216,8 +199,8 @@ static void rb_shell_sync_smalldisplay (RBShell *shell);
 static void rb_shell_sync_pane_visibility (RBShell *shell);
 static void rb_shell_sync_statusbar_visibility (RBShell *shell);
 static void rb_shell_set_visibility (RBShell *shell,
-				     gboolean visible,
-				     gboolean force);
+				     gboolean initial,
+				     gboolean visible);
 static void sidepane_visibility_changed_cb (GConfClient *client,
 					    guint cnxn_id,
 					    GConfEntry *entry,
@@ -237,9 +220,6 @@ static void sourcelist_drag_received_cb (RBSourceList *sourcelist,
 static gboolean rb_shell_show_popup_cb (RBSourceList *sourcelist,
 					RBSource *target,
 					RBShell *shell);
-static gboolean tray_destroy_cb (GtkObject *object, RBShell *shell);
-static void rb_shell_construct_notify_titles (RBShell *shell,
-					      RhythmDBEntry *entry);
 
 static void paned_size_allocate_cb (GtkWidget *widget,
 				    GtkAllocation *allocation,
@@ -256,6 +236,8 @@ static void rb_shell_player_volume_changed_cb (RBShellPlayer *player,
 
 static void rb_shell_session_init (RBShell *shell);
 
+static gboolean rb_shell_visibility_changing (RBShell *shell, gboolean initial, gboolean visible);
+
 enum
 {
 	PROP_NONE,
@@ -296,8 +278,11 @@ enum
 enum
 {
 	VISIBILITY_CHANGED,
+	VISIBILITY_CHANGING,
 	CREATE_SONG_INFO,
 	REMOVABLE_MEDIA_SCAN_FINISHED,
+	NOTIFY_PLAYING_ENTRY,
+	NOTIFY_CUSTOM,
 	LAST_SIGNAL
 };
 
@@ -309,7 +294,6 @@ struct RBShellPrivate
 {
 	GtkWidget *window;
 	gboolean iconified;
-	guint idle_hide_mainwindow_id;
 
 	GtkUIManager *ui_manager;
 	GtkActionGroup *actiongroup;
@@ -352,8 +336,6 @@ struct RBShellPrivate
 	RBPlaylistManager *playlist_manager;
 	RBRemovableMediaManager *removable_media_manager;
 
-	GList *supported_media_extensions;
-
 	RBLibrarySource *library_source;
 	RBPodcastSource *podcast_source;
 	RBPlaylistSource *queue_source;
@@ -367,19 +349,12 @@ struct RBShellPrivate
 	GtkWidget *prefs;
 	GtkWidget *plugins;
 
-	RBTrayIcon *tray_icon;
 	GtkWidget *volume_button;
 	gboolean syncing_volume;
 
 	char *cached_title;
-	char *cached_duration;
 	gboolean cached_playing;
 
-	/* markup, used for notifications and for tray tooltips */
-	char *cached_notify_primary;
-	char *cached_notify_secondary;
-	GdkPixbuf *cached_art_icon;
-
 	guint sidepane_visibility_notify_id;
 	guint toolbar_visibility_notify_id;
 	guint toolbar_style_notify_id;
@@ -428,9 +403,6 @@ static GtkActionEntry rb_shell_actions [] =
 	{ "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1",
 	  N_("Display music player help"),
 	  G_CALLBACK (rb_shell_cmd_contents) },
-	{ "MusicClose", GTK_STOCK_CLOSE, N_("_Close"), "<control>W",
-	  N_("Hide the music player window"),
-	  G_CALLBACK (rb_shell_cmd_toggle_visibility) },
 	{ "MusicQuit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q",
 	  N_("Quit the music player"),
 	  G_CALLBACK (rb_shell_cmd_quit) },
@@ -482,6 +454,8 @@ rb_shell_class_init (RBShellClass *klass)
         object_class->finalize = rb_shell_finalize;
 	object_class->constructor = rb_shell_constructor;
 
+	klass->visibility_changing = rb_shell_visibility_changing;
+
 	g_object_class_install_property (object_class,
 					 PROP_NO_REGISTRATION,
 					 g_param_spec_boolean ("no-registration",
@@ -657,6 +631,17 @@ rb_shell_class_init (RBShellClass *klass)
 			      G_TYPE_NONE,
 			      1,
 			      G_TYPE_BOOLEAN);
+	rb_shell_signals[VISIBILITY_CHANGING] =
+		g_signal_new ("visibility_changing",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (RBShellClass, visibility_changing),
+			      NULL, NULL,
+			      rb_marshal_BOOLEAN__BOOLEAN_BOOLEAN,
+			      G_TYPE_BOOLEAN,
+			      2,
+			      G_TYPE_BOOLEAN,
+			      G_TYPE_BOOLEAN);
 
 	rb_shell_signals[CREATE_SONG_INFO] =
 		g_signal_new ("create_song_info",
@@ -677,6 +662,26 @@ rb_shell_class_init (RBShellClass *klass)
 			      g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE,
 			      0);
+	rb_shell_signals[NOTIFY_PLAYING_ENTRY] =
+		g_signal_new ("notify-playing-entry",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__BOOLEAN,
+			      G_TYPE_NONE,
+			      1,
+			      G_TYPE_BOOLEAN);
+	rb_shell_signals[NOTIFY_CUSTOM] =
+		g_signal_new ("notify-custom",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      0,
+			      NULL, NULL,
+			      rb_marshal_VOID__UINT_STRING_STRING_OBJECT_BOOLEAN,
+			      G_TYPE_NONE,
+			      5,
+			      G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN);
 
 	g_type_class_add_private (klass, sizeof (RBShellPrivate));
 }
@@ -723,7 +728,7 @@ rb_shell_set_property (GObject *object,
 		shell->priv->playlists_file = g_value_dup_string (value);
 		break;
 	case PROP_VISIBILITY:
-		rb_shell_set_visibility (shell, g_value_get_boolean (value), FALSE);
+		rb_shell_set_visibility (shell, FALSE, g_value_get_boolean (value));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -871,7 +876,6 @@ rb_shell_shutdown (RBShell *shell)
 	/* Hide the main window and tray icon as soon as possible */
 	display = gtk_widget_get_display (shell->priv->window);
 	gtk_widget_hide (shell->priv->window);
-	gtk_widget_hide (GTK_WIDGET (shell->priv->tray_icon));
 	gdk_display_sync (display);
 }
 
@@ -890,18 +894,8 @@ rb_shell_finalize (GObject *object)
 	eel_gconf_notification_remove (shell->priv->toolbar_style_notify_id);
 	eel_gconf_notification_remove (shell->priv->smalldisplay_notify_id);
 
-	g_list_free (shell->priv->supported_media_extensions);
-
-	gtk_widget_destroy (GTK_WIDGET (shell->priv->tray_icon));
-
-	g_free (shell->priv->cached_notify_primary);
-	g_free (shell->priv->cached_notify_secondary);
-
 	g_free (shell->priv->cached_title);
 
-	if (shell->priv->cached_art_icon != NULL)
-		g_object_unref (shell->priv->cached_art_icon);
-
 	if (shell->priv->save_playlist_id > 0) {
 		g_source_remove (shell->priv->save_playlist_id);
 		shell->priv->save_playlist_id = 0;
@@ -1069,10 +1063,6 @@ construct_widgets (RBShell *shell)
 				 G_CALLBACK (rb_shell_playing_source_changed_cb),
 				 shell, 0);
 	g_signal_connect_object (G_OBJECT (shell->priv->player_shell),
-				 "playing-song-changed",
-				 G_CALLBACK (rb_shell_playing_entry_changed_cb),
-				 shell, 0);
-	g_signal_connect_object (G_OBJECT (shell->priv->player_shell),
 				 "notify::playing-from-queue",
 				 G_CALLBACK (rb_shell_playing_from_queue_cb),
 				 shell, 0);
@@ -1080,10 +1070,6 @@ construct_widgets (RBShell *shell)
 				 "window_title_changed",
 				 G_CALLBACK (rb_shell_player_window_title_changed_cb),
 				 shell, 0);
-	g_signal_connect_object (G_OBJECT (shell->priv->player_shell),
-				 "elapsed_changed",
-				 G_CALLBACK (rb_shell_player_elapsed_changed_cb),
-				 shell, 0);
 	shell->priv->clipboard_shell = rb_shell_clipboard_new (shell->priv->actiongroup,
 							       shell->priv->ui_manager,
 							       shell->priv->db);
@@ -1352,9 +1338,6 @@ rb_shell_constructor (GType type,
 	/* initialize shell services */
 	construct_widgets (shell);
 
-	rb_debug ("shell: setting up tray icon");
-	tray_destroy_cb (NULL, shell);
-
 	rb_debug ("shell: adding gconf notification");
 	/* sync state */
 	shell->priv->sidepane_visibility_notify_id =
@@ -1396,10 +1379,6 @@ rb_shell_constructor (GType type,
 	g_signal_connect_object (G_OBJECT (shell->priv->db), "entry-added",
 				 G_CALLBACK (rb_shell_db_entry_added_cb), shell, 0);
 
-	g_signal_connect_object (G_OBJECT (shell->priv->db),
-				 "entry_extra_metadata_notify::rb:coverArt",
-				 G_CALLBACK (rb_shell_db_metadata_art_cb), shell, 0);
-
 	construct_sources (shell);
 
 	construct_load_ui (shell);
@@ -1423,13 +1402,14 @@ rb_shell_constructor (GType type,
 
 	rb_debug ("shell: syncing window state");
 	rb_shell_sync_paned (shell);
-	gtk_widget_show_all (GTK_WIDGET (shell->priv->tray_icon));
 
 	/* Do as if we ran the first time druid */
 	if (!eel_gconf_get_boolean (CONF_FIRST_TIME))
 		eel_gconf_set_boolean (CONF_FIRST_TIME, TRUE);
 
-	rb_shell_set_visibility (shell, eel_gconf_get_boolean (CONF_STATE_WINDOW_VISIBLE), TRUE);
+	/* set initial visibility */
+	rb_shell_set_visibility (shell, TRUE, TRUE);
+
 	gdk_notify_startup_complete ();
 
 	/* focus play if small, the entry view if not */
@@ -1450,30 +1430,6 @@ rb_shell_constructor (GType type,
 	return G_OBJECT (shell);
 }
 
-/* Based on a function found in wnck */
-static void
-set_icon_geometry  (GdkWindow *window,
-		    int        x,
-		    int        y,
-		    int        width,
-		    int        height)
-{
-	gulong data[4];
-	Display *dpy = gdk_x11_drawable_get_xdisplay (window);
-
-	data[0] = x;
-	data[1] = y;
-	data[2] = width;
-	data[3] = height;
-
-	XChangeProperty (dpy,
-			 GDK_WINDOW_XID (window),
-			 gdk_x11_get_xatom_by_name_for_display (gdk_drawable_get_display (window),
-								"_NET_WM_ICON_GEOMETRY"),
-			 XA_CARDINAL, 32, PropModeReplace,
-			 (guchar *)&data, 4);
-}
-
 static gboolean
 rb_shell_window_state_cb (GtkWidget *widget,
 			  GdkEventWindowState *event,
@@ -1508,6 +1464,12 @@ rb_shell_window_state_cb (GtkWidget *widget,
 }
 
 static gboolean
+rb_shell_visibility_changing (RBShell *shell, gboolean initial, gboolean visible)
+{
+	return visible;
+}
+
+static gboolean
 rb_shell_get_visibility (RBShell *shell)
 {
 	GdkWindowState state;
@@ -1524,51 +1486,27 @@ rb_shell_get_visibility (RBShell *shell)
 	return TRUE;
 }
 
-static gboolean
-idle_hide_mainwindow (gpointer data)
-{
-	RBShell *shell = RB_SHELL (data);
-
-	GDK_THREADS_ENTER ();
-
-	gtk_widget_hide (GTK_WIDGET (shell->priv->window));
-
-	g_signal_emit (shell, rb_shell_signals[VISIBILITY_CHANGED], 0, FALSE);
-
-	g_object_unref (shell);
-
-	GDK_THREADS_LEAVE ();
-
-	return FALSE;
-}
-
 static void
 rb_shell_set_visibility (RBShell *shell,
-			 gboolean visible,
-			 gboolean force)
+			 gboolean initial,
+			 gboolean visible)
 {
-	gboolean current_visible;
+	gboolean really_visible;
 
 	rb_profile_start ("changing shell visibility");
 
-	current_visible = rb_shell_get_visibility (shell);
-	if (!force && visible == current_visible) {
+	if (visible == rb_shell_get_visibility (shell)) {
 		rb_profile_end ("changing shell visibility");
 		return;
 	}
 
-	/* FIXME - see below */
-	if (shell->priv->idle_hide_mainwindow_id > 0)
-		g_source_remove (shell->priv->idle_hide_mainwindow_id);
-	shell->priv->idle_hide_mainwindow_id = 0;
+	really_visible = visible;
+	g_signal_emit (shell, rb_shell_signals[VISIBILITY_CHANGING], 0, initial, visible, &really_visible);
 
-	/* don't minimise if we have no tray icon */
-	if (visible || (!force && !egg_tray_icon_have_manager (EGG_TRAY_ICON (shell->priv->tray_icon)))) {
+	if (really_visible) {
 		rb_debug ("showing main window");
 		rb_shell_sync_window_state (shell, FALSE);
 
-		if (egg_tray_icon_have_manager (EGG_TRAY_ICON (shell->priv->tray_icon)))
-			gtk_window_set_skip_taskbar_hint (GTK_WINDOW (shell->priv->window), FALSE);
 		gtk_widget_show (GTK_WIDGET (shell->priv->window));
 		gtk_window_deiconify (GTK_WINDOW (shell->priv->window));
 
@@ -1578,30 +1516,12 @@ rb_shell_set_visibility (RBShell *shell,
 			gtk_widget_show_all (GTK_WIDGET (shell->priv->window));
 
 		g_signal_emit (shell, rb_shell_signals[VISIBILITY_CHANGED], 0, visible);
-
-		eel_gconf_set_boolean (CONF_STATE_WINDOW_VISIBLE, TRUE);
 	} else {
-		int x, y, width, height;
-
 		rb_debug ("hiding main window");
 		shell->priv->iconified = TRUE;
-		rb_tray_icon_get_geom (shell->priv->tray_icon,
-				       &x, &y, &width, &height);
-		if (GTK_WIDGET_REALIZED (GTK_WIDGET (shell->priv->window)))
-			set_icon_geometry (GTK_WIDGET (shell->priv->window)->window,
-					   x, y, width, height);
-		if (egg_tray_icon_have_manager (EGG_TRAY_ICON (shell->priv->tray_icon)))
-			gtk_window_set_skip_taskbar_hint (GTK_WINDOW (shell->priv->window), TRUE);
 		gtk_window_iconify (GTK_WINDOW (shell->priv->window));
 
-		/* FIMXE - this is horribly evil racy workaround for a
-		 * current bug in the tasklist not noticing our hint
-		 * change
-		 */
-		shell->priv->idle_hide_mainwindow_id =
-			g_timeout_add (250, idle_hide_mainwindow, g_object_ref (shell));
-
-		eel_gconf_set_boolean (CONF_STATE_WINDOW_VISIBLE, FALSE);
+		g_signal_emit (shell, rb_shell_signals[VISIBILITY_CHANGED], 0, FALSE);
 	}
 
 	rb_profile_end ("changing shell visibility");
@@ -1797,50 +1717,6 @@ rb_shell_db_entry_added_cb (RhythmDB *db,
 	}
 }
 
-static void
-rb_shell_db_metadata_art_cb (RhythmDB *db,
-			     RhythmDBEntry *entry,
-			     const char *field,
-			     GValue *metadata,
-			     RBShell *shell)
-{
-	RhythmDBEntry *playing_entry;
-	guint time;
-
-	playing_entry = rb_shell_player_get_playing_entry (shell->priv->player_shell);
-	if (playing_entry == NULL)
-		return;
-
-	if (entry != playing_entry) {
-		rhythmdb_entry_unref (playing_entry);
-		return;
-	}
-
-	if (shell->priv->cached_art_icon != NULL) {
-		g_object_unref (shell->priv->cached_art_icon);
-		shell->priv->cached_art_icon = NULL;
-	}
-
-	if (G_VALUE_HOLDS (metadata, GDK_TYPE_PIXBUF)) {
-		GdkPixbuf *pixbuf;
-
-		pixbuf = GDK_PIXBUF (g_value_get_object (metadata));
-		if (pixbuf != NULL) {
-			shell->priv->cached_art_icon = rb_scale_pixbuf_to_size (pixbuf, GTK_ICON_SIZE_DIALOG);
-		}
-	}
-
-	rb_tray_icon_set_tooltip_icon (shell->priv->tray_icon,
-				       shell->priv->cached_art_icon);
-
-	if (rb_shell_player_get_playing_time (shell->priv->player_shell, &time, NULL)) {
-		if (time < PLAYING_ENTRY_NOTIFY_TIME)
-			rb_shell_notify_playing_entry (shell, entry, FALSE);
-	}
-
-	rhythmdb_entry_unref (playing_entry);
-}
-
 RBSource *
 rb_shell_get_source_by_entry_type (RBShell *shell,
 				   RhythmDBEntryType type)
@@ -2026,22 +1902,6 @@ rb_shell_playing_from_queue_cb (RBShellPlayer *player,
 }
 
 static void
-rb_shell_playing_entry_changed_cb (RBShellPlayer *player,
-				   RhythmDBEntry *entry,
-				   RBShell *shell)
-{
-	if (shell->priv->cached_art_icon != NULL)
-		g_object_unref (shell->priv->cached_art_icon);
-	shell->priv->cached_art_icon = NULL;
-
-	rb_shell_notify_playing_entry (shell, entry, FALSE);
-
-	rb_tray_icon_set_tooltip_primary_text (shell->priv->tray_icon, shell->priv->cached_notify_primary);
-	rb_tray_icon_set_tooltip_icon (shell->priv->tray_icon, shell->priv->cached_art_icon);
-	rb_shell_update_tray_tooltip_elapsed (shell);
-}
-
-static void
 merge_source_ui_cb (const char *action,
 		    RBShell *shell)
 {
@@ -2107,59 +1967,7 @@ rb_shell_player_window_title_changed_cb (RBShellPlayer *player,
 					 const char *window_title,
 					 RBShell *shell)
 {
-	RhythmDBEntry *entry;
 	rb_shell_set_window_title (shell, window_title);
-
-	/* also update the tooltip; this is slightly weird,
-	 * but this is the most useful way to identify
-	 * track changes in radio streams.
-	 */
-	entry = rb_shell_player_get_playing_entry (shell->priv->player_shell);
-	rb_shell_construct_notify_titles (shell, entry);
-	rb_tray_icon_set_tooltip_primary_text (shell->priv->tray_icon, shell->priv->cached_notify_primary);
-	rb_shell_update_tray_tooltip_elapsed (shell);
-	
-	if (entry)
-		rhythmdb_entry_unref (entry);
-}
-
-static void
-rb_shell_player_elapsed_changed_cb (RBShellPlayer *player,
-				    guint elapsed,
-				    RBShell *shell)
-{
-	rb_shell_update_tray_tooltip_elapsed (shell);
-}
-
-static void
-rb_shell_update_tray_tooltip_elapsed (RBShell *shell)
-{
-	gboolean playing;
-	char *elapsed_string;
-	GString *secondary;
-
-	rb_shell_player_get_playing (shell->priv->player_shell, &playing, NULL);
-	elapsed_string = rb_shell_player_get_playing_time_string (shell->priv->player_shell);
-
-	secondary = g_string_sized_new (100);
-	if (shell->priv->cached_notify_secondary != NULL) {
-		g_string_append (secondary, shell->priv->cached_notify_secondary);
-		if (secondary->len != 0)
-			g_string_append_c (secondary, '\n');
-	}
-	if (shell->priv->cached_notify_primary == NULL) {
-		g_string_append (secondary, _("Not playing"));
-	} else if (!playing) {
-		/* Translators: the %s is the elapsed and total time */
-		g_string_append_printf (secondary, _("Paused, %s"), elapsed_string);
-	} else {
-		g_string_append (secondary, elapsed_string);
-	}
-
-	rb_tray_icon_set_tooltip_secondary_markup (shell->priv->tray_icon,
-						   secondary->str);
-	g_free (elapsed_string);
-	g_string_free (secondary, TRUE);
 }
 
 static void
@@ -2351,14 +2159,7 @@ rb_shell_toggle_visibility (RBShell *shell)
 
 	visible = rb_shell_get_visibility (shell);
 
-	rb_shell_set_visibility (shell, !visible, FALSE);
-}
-
-static void
-rb_shell_cmd_toggle_visibility (GtkAction *action,
-				RBShell *shell)
-{
-	rb_shell_toggle_visibility (shell);
+	rb_shell_set_visibility (shell, FALSE, !visible);
 }
 
 static void
@@ -2710,8 +2511,6 @@ rb_shell_sync_party_mode (RBShell *shell)
 	   should not be persistent */
 
 	/* disable/enable quit action */
-	action = gtk_action_group_get_action (shell->priv->actiongroup, "MusicClose");
-	g_object_set (G_OBJECT (action), "sensitive", !shell->priv->party_mode, NULL);
 	action = gtk_action_group_get_action (shell->priv->actiongroup, "MusicQuit");
 	g_object_set (G_OBJECT (action), "sensitive", !shell->priv->party_mode, NULL);
 	action = gtk_action_group_get_action (shell->priv->actiongroup, "ViewSmallDisplay");
@@ -2959,215 +2758,21 @@ rb_shell_show_popup_cb (RBSourceList *sourcelist,
 	return rb_source_show_popup (target);
 }
 
-static void
-tray_embedded_cb (GtkPlug *plug,
-		  gpointer data)
-{
-	/* FIXME - this doens't work */
-#if 0
-	RBShell *shell = RB_SHELL (data);
-
-	rb_debug ("got embedded signal");
-
-	gdk_window_set_decorations (shell->priv->window->window,
-				    GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
-#endif
-}
-
-static gboolean
-tray_destroy_cb (GtkObject *object,
-		 RBShell *shell)
-{
-	if (shell->priv->tray_icon) {
-		rb_debug ("caught destroy event for tray icon %p", object);
-		g_object_ref_sink (object);
-		shell->priv->tray_icon = NULL;
-		rb_debug ("finished sinking tray");
-	}
-
-	rb_debug ("creating new tray icon");
-	shell->priv->tray_icon = rb_tray_icon_new (shell->priv->ui_manager, shell);
-	g_signal_connect_object (G_OBJECT (shell->priv->tray_icon), "destroy",
-				 G_CALLBACK (tray_destroy_cb), shell, 0);
-	g_signal_connect_object (G_OBJECT (shell->priv->tray_icon), "embedded",
-				 G_CALLBACK (tray_embedded_cb), shell, 0);
-
- 	gtk_widget_show_all (GTK_WIDGET (shell->priv->tray_icon));
-
-	rb_debug ("done creating new tray icon %p", shell->priv->tray_icon);
- 	return TRUE;
-}
-
-static gchar *
-markup_escape (const char *text)
-{
-	return (text == NULL) ? NULL : g_markup_escape_text (text, -1);
-}
-
-static void
-rb_shell_construct_notify_titles (RBShell *shell,
-				  RhythmDBEntry *entry)
-{
-	GValue *value;
-	const char *stream_title = NULL;
-	char *artist = NULL;
-	char *album = NULL;
-	char *title = NULL;
-	GString *secondary;
-
-	g_free (shell->priv->cached_notify_primary);
-	g_free (shell->priv->cached_notify_secondary);
-	shell->priv->cached_notify_primary = NULL;
-	shell->priv->cached_notify_secondary = NULL;
-
-	if (entry == NULL)
-		return;
-
-	secondary = g_string_sized_new (100);
-
-	/* get artist, preferring streaming song details */
-	value = rhythmdb_entry_request_extra_metadata (shell->priv->db,
-						       entry,
-						       RHYTHMDB_PROP_STREAM_SONG_ARTIST);
-	if (value != NULL) {
-		artist = markup_escape (g_value_get_string (value));
-		g_value_unset (value);
-		g_free (value);
-	} else {
-		artist = markup_escape (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
-	}
-
-	if (artist != NULL && artist[0] != '\0') {
-		/* Translators: by Artist */
-		g_string_append_printf (secondary, _("by <i>%s</i>"), artist);
-	}
-	g_free (artist);
-
-	/* get album, preferring streaming song details */
-	value = rhythmdb_entry_request_extra_metadata (shell->priv->db,
-						       entry,
-						       RHYTHMDB_PROP_STREAM_SONG_ALBUM);
-	if (value != NULL) {
-		album = markup_escape (g_value_get_string (value));
-		g_value_unset (value);
-		g_free (value);
-	} else {
-		album = markup_escape (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
-	}
-
-	if (album != NULL && album[0] != '\0') {
-		if (secondary->len != 0)
-			g_string_append_c (secondary, ' ');
-
-		/* Translators: from Album */
-		g_string_append_printf (secondary, _("from <i>%s</i>"), album);
-	}
-	g_free (album);
-
-	/* get title and possibly stream name.
-	 * if we have a streaming song title, the entry's title
-	 * property is the stream name.
-	 */
-	value = rhythmdb_entry_request_extra_metadata (shell->priv->db,
-						       entry,
-						       RHYTHMDB_PROP_STREAM_SONG_TITLE);
-	if (value != NULL) {
-		title = g_value_dup_string (value);
-		g_value_unset (value);
-		g_free (value);
-
-		stream_title = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
-	} else {
-		title = g_strdup (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
-	}
-
-	if (stream_title != NULL && stream_title[0] != '\0') {
-		char *escaped;
-
-		escaped = markup_escape (stream_title);
-		if (secondary->len == 0)
-			g_string_append (secondary, escaped);
-		else
-			g_string_append_printf (secondary, " (%s)", escaped);
-		g_free (escaped);
-	}
-
-	if (title != NULL)
-		shell->priv->cached_notify_primary = title;
-	else
-		/* Translators: unknown track title */
-		shell->priv->cached_notify_primary = g_strdup (_("Unknown"));
-
-	shell->priv->cached_notify_secondary = g_string_free (secondary, FALSE);
-}
-
-void
-rb_shell_notify_playing_entry (RBShell *shell,
-			       RhythmDBEntry *entry,
-			       gboolean requested)
-{
-	rb_shell_construct_notify_titles (shell, entry);
-
-	if (entry == NULL)
-		return;
-
-	rb_shell_hidden_notify_markup (shell,
-				       PLAYING_ENTRY_NOTIFY_TIME * 1000,
-				       shell->priv->cached_notify_primary,
-				       shell->priv->cached_art_icon,
-				       shell->priv->cached_notify_secondary,
-				       requested);
-}
-
 void
-rb_shell_hidden_notify (RBShell *shell,
+rb_shell_notify_custom (RBShell *shell,
 			guint timeout,
 			const char *primary,
-			GdkPixbuf *pixbuf,
 			const char *secondary,
+			GdkPixbuf *pixbuf,
 			gboolean requested)
 {
-	char *primary_markup = g_markup_escape_text (primary, -1);
-	char *secondary_markup = g_markup_escape_text (secondary, -1);
-
-	rb_shell_hidden_notify_markup (shell, timeout, primary_markup, 
-				       pixbuf, secondary_markup, requested);
-
-	g_free (primary_markup);
-	g_free (secondary_markup);
-}
-
-void
-rb_shell_hidden_notify_markup (RBShell *shell,
-			       guint timeout,
-			       const char *primary_markup,
-			       GdkPixbuf *pixbuf,
-			       const char *secondary_markup,
-			       gboolean requested)
-{
-
-	if (requested == FALSE && rb_shell_get_visibility (shell)) {
-		rb_debug ("shell is visible, not notifying");
-		return;
-	}
-
-	rb_tray_icon_notify (shell->priv->tray_icon,
-			     timeout,
-			     primary_markup,
-			     pixbuf,
-			     secondary_markup,
-			     requested);
+	g_signal_emit (shell, rb_shell_signals[NOTIFY_CUSTOM], 0, timeout, primary, secondary, pixbuf, requested);
 }
 
 gboolean
 rb_shell_do_notify (RBShell *shell, gboolean requested, GError **error)
 {
-	RhythmDBEntry *entry;
-
-	entry = rb_shell_player_get_playing_entry (shell->priv->player_shell);
-	rb_shell_notify_playing_entry (shell, entry, requested);
-	rhythmdb_entry_unref (entry);
-
+	g_signal_emit (shell, rb_shell_signals[NOTIFY_PLAYING_ENTRY], 0, requested);
 	return TRUE;
 }
 
diff --git a/shell/rb-shell.h b/shell/rb-shell.h
index 4932699..fca025c 100644
--- a/shell/rb-shell.h
+++ b/shell/rb-shell.h
@@ -82,9 +82,10 @@ typedef struct
         GObjectClass parent_class;
 
 	/* signals */
-	void	(*visibility_changed)	(RBShell *shell, gboolean visible);
-	void	(*create_song_info)	(RBShell *shell, RBSongInfo *song_info, gboolean multi);
-	void	(*removable_media_scan_finished) (RBShell *shell);
+	gboolean (*visibility_changing)	(RBShell *shell, gboolean initial, gboolean visible);
+	void	 (*visibility_changed)	(RBShell *shell, gboolean visible);
+	void	 (*create_song_info)	(RBShell *shell, RBSongInfo *song_info, gboolean multi);
+	void	 (*removable_media_scan_finished) (RBShell *shell);
 } RBShellClass;
 
 GType		rb_shell_get_type	(void);
@@ -140,21 +141,12 @@ gboolean	rb_shell_clear_queue (RBShell *shell,
 gboolean	rb_shell_quit (RBShell *shell,
 			       GError **error);
 
-void            rb_shell_hidden_notify  (RBShell *shell,
+void            rb_shell_notify_custom  (RBShell *shell,
 					 guint timeout,
 					 const char *primary,
-					 GdkPixbuf *pixbuf,
 					 const char *secondary,
+					 GdkPixbuf *pixbuf,
 					 gboolean requested);
-void            rb_shell_hidden_notify_markup  (RBShell *shell,
-						guint timeout,
-						const char *primary_markup,
-						GdkPixbuf *pixbuf,
-						const char *secondary_markup,
-						gboolean requested);
-void		rb_shell_notify_playing_entry (RBShell *shell,
-					       RhythmDBEntry *entry,
-					       gboolean requested);
 gboolean	rb_shell_do_notify (RBShell *shell,
 				    gboolean requested,
 				    GError **error);
diff --git a/shell/rb-tray-icon.c b/shell/rb-tray-icon.c
deleted file mode 100644
index a14f223..0000000
--- a/shell/rb-tray-icon.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- *  arch-tag: Implementation of Rhythmbox tray icon object
- *
- *  Copyright (C) 2003,2004 Colin Walters <walters redhat com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The Rhythmbox authors hereby grant permission for non-GPL compatible
- *  GStreamer plugins to be used and distributed together with GStreamer
- *  and Rhythmbox. This permission is above and beyond the permissions granted
- *  by the GPL license by which Rhythmbox is covered. If you modify this code
- *  you may extend this exception to your version of the code, but you are not
- *  obligated to do so. If you do not wish to do so, delete this exception
- *  statement from your version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
- *
- */
-
-#include <config.h>
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-
-#include "rb-tray-icon.h"
-#include "rb-stock-icons.h"
-#include "rb-debug.h"
-#include "eel-gconf-extensions.h"
-#include "rb-preferences.h"
-#include "rb-shell.h"
-#include "rb-shell-player.h"
-#include "rb-util.h"
-
-#define TRAY_ICON_DEFAULT_TOOLTIP _("Music Player")
-
-#define TOOLTIP_IMAGE_BORDER_WIDTH	1
-
-/**
- * SECTION:rb-tray-icon
- * @short_description: Notification area icon
- *
- * The tray icon handles a few different forms of input:
- * <itemizedlist>
- *   <listitem>left clicking hides and shows the main window</listitem>
- *   <listitem>right clicking brings up a popup menu</listitem>
- *   <listitem>dropping files on the icon adds them to the library</listitem>
- *   <listitem>scroll events change the playback volume</listitem>
- * </itemizedlist>
- *
- * The tooltip for the tray icon consists of an image, the primary text 
- * (displayed in bold large type), and the secondary text (which can
- * contain markup).
- *
- * The tooltip is shown after the mouse pointer has been within the tray
- * icon area for half a second.  This delay is only reset once the pointer
- * has been outside the tray icon area for more than one second.
- *
- * The tray icon can also display notification bubbles (using libnotify).
- * These contain the same set of elements as the tooltip.  The tooltip is
- * suppressed while a notification bubble is being displayed.  A GConf setting
- * allows the user to disable notification bubbles.
- */
-
-static void rb_tray_icon_class_init (RBTrayIconClass *klass);
-static void rb_tray_icon_init (RBTrayIcon *shell_player);
-static GObject *rb_tray_icon_constructor (GType type, guint n_construct_properties,
-					  GObjectConstructParam *construct_properties);
-static void rb_tray_icon_dispose (GObject *object);
-static void rb_tray_icon_finalize (GObject *object);
-static void rb_tray_icon_sync_action (RBShell *shell,
-				      gboolean visible,
-				      RBTrayIcon *tray);
-static void rb_tray_icon_set_property (GObject *object,
-					  guint prop_id,
-					  const GValue *value,
-					  GParamSpec *pspec);
-static void rb_tray_icon_get_property (GObject *object,
-					  guint prop_id,
-					  GValue *value,
-					  GParamSpec *pspec);
-static void rb_tray_icon_button_press_event_cb (GtkWidget *ebox, GdkEventButton *event,
-						RBTrayIcon *icon);
-static void rb_tray_icon_scroll_event_cb (GtkWidget *ebox, GdkEvent *event,
-						RBTrayIcon *icon);
-static void rb_tray_icon_show_window_changed_cb (GtkAction *action,
-						 RBTrayIcon *icon);
-static void rb_tray_icon_show_notifications_changed_cb (GtkAction *action,
-							RBTrayIcon *icon);
-static void rb_tray_icon_drop_cb (GtkWidget *widget,
-				  GdkDragContext *context,
-				  gint x,
-				  gint y,
-				  GtkSelectionData *data,
-				  guint info,
-				  guint time,
-				  RBTrayIcon *icon);
-static void rb_tray_icon_suppress_tooltips (RBTrayIcon *icon, guint duration);
-static gboolean tray_icon_tooltip_cb (GtkWidget  *widget,
-				      gint        x,
-				      gint        y,
-				      gboolean    keyboard_tooltip,
-				      GtkTooltip *tooltip,
-				      RBTrayIcon *icon);
-
-struct RBTrayIconPrivate
-{
-	GtkUIManager *ui_manager;
-	GtkActionGroup *actiongroup;
-
-	GtkWidget *playing_image;
-	GtkWidget *not_playing_image;
-	GtkWidget *ebox;
-
-	char *primary_text;
-	char *secondary_markup;
-	GdkPixbuf *app_pixbuf;
-	GdkPixbuf *pixbuf;
-
-	gboolean tooltips_suppressed;
-	guint tooltip_unsuppress_id;
-
-	RBShell *shell;
-	RBShellPlayer *shell_player;
-
-	gboolean show_notifications;
-};
-
-#define RB_TRAY_ICON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_TRAY_ICON, RBTrayIconPrivate))
-
-enum
-{
-	PROP_0,
-	PROP_UI_MANAGER,
-	PROP_ACTION_GROUP,
-	PROP_SHELL
-};
-
-enum
-{
-	LAST_SIGNAL,
-};
-
-static GtkToggleActionEntry rb_tray_icon_toggle_entries [] =
-{
-	{ "TrayShowWindow", NULL, N_("_Show Music Player"), NULL,
-	  N_("Choose music to play"),
-	  G_CALLBACK (rb_tray_icon_show_window_changed_cb) },
-	{ "TrayShowNotifications", NULL, N_("Show N_otifications"), NULL,
-	  N_("Show notifications of song changes and other events"),
-	  G_CALLBACK (rb_tray_icon_show_notifications_changed_cb) }
-};
-static guint rb_tray_icon_n_toggle_entries = G_N_ELEMENTS (rb_tray_icon_toggle_entries);
-
-static const GtkTargetEntry target_uri [] = {{ "text/uri-list", 0, 0 }};
-
-G_DEFINE_TYPE (RBTrayIcon, rb_tray_icon, EGG_TYPE_TRAY_ICON)
-
-static void
-rb_tray_icon_class_init (RBTrayIconClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	object_class->dispose = rb_tray_icon_dispose;
-	object_class->finalize = rb_tray_icon_finalize;
-	object_class->constructor = rb_tray_icon_constructor;
-
-	object_class->set_property = rb_tray_icon_set_property;
-	object_class->get_property = rb_tray_icon_get_property;
-
-	/**
-	 * RBTrayIcon:shell:
-	 *
-	 * #RBShell instance
-	 */
-	g_object_class_install_property (object_class,
-					 PROP_SHELL,
-					 g_param_spec_object ("shell",
-							      "RBShell",
-							      "RBShell object",
-							      RB_TYPE_SHELL,
-							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-	/**
-	 * RBTrayIcon:ui-manager:
-	 *
-	 * #GtkUIManager instance
-	 */
-	g_object_class_install_property (object_class,
-					 PROP_UI_MANAGER,
-					 g_param_spec_object ("ui-manager",
-							      "GtkUIManager",
-							      "GtkUIManager object",
-							      GTK_TYPE_UI_MANAGER,
-							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-	/**
-	 * RBTrayIcon:action-group:
-	 *
-	 * The #GtkActionGroup containing action specific to the tray icon
-	 */
-	g_object_class_install_property (object_class,
-					 PROP_ACTION_GROUP,
-					 g_param_spec_object ("action-group",
-							      "GtkActionGroup",
-							      "GtkActionGroup object",
-							      GTK_TYPE_ACTION_GROUP,
-							      G_PARAM_READABLE));
-
-	g_type_class_add_private (klass, sizeof (RBTrayIconPrivate));
-}
-
-static void
-rb_tray_icon_init (RBTrayIcon *icon)
-{
-	GtkIconTheme *theme;
-	gint size;
-
-	rb_debug ("setting up tray icon");
-
-	icon->priv = RB_TRAY_ICON_GET_PRIVATE (icon);
-
-	g_object_set (icon, "has-tooltip", TRUE, NULL);
-	g_signal_connect_object (icon, "query-tooltip",
-				 G_CALLBACK (tray_icon_tooltip_cb),
-				 icon, 0);
-
-	icon->priv->ebox = gtk_event_box_new ();
-	g_signal_connect_object (G_OBJECT (icon->priv->ebox),
-				 "button_press_event",
-				 G_CALLBACK (rb_tray_icon_button_press_event_cb),
-				 icon, 0);
-	g_signal_connect_object (G_OBJECT (icon->priv->ebox),
-				 "scroll_event",
-				 G_CALLBACK (rb_tray_icon_scroll_event_cb),
-				 icon, 0);
-
-	gtk_drag_dest_set (icon->priv->ebox, GTK_DEST_DEFAULT_ALL, target_uri, 1, GDK_ACTION_COPY);
-	g_signal_connect_object (G_OBJECT (icon->priv->ebox), "drag_data_received",
-				 G_CALLBACK (rb_tray_icon_drop_cb), icon, 0);
-
-	icon->priv->playing_image = gtk_image_new_from_icon_name (RB_STOCK_TRAY_ICON_PLAYING,
-								  GTK_ICON_SIZE_SMALL_TOOLBAR);
-	icon->priv->not_playing_image = gtk_image_new_from_icon_name (RB_STOCK_TRAY_ICON_NOT_PLAYING,
-								      GTK_ICON_SIZE_SMALL_TOOLBAR);
-	g_object_ref (icon->priv->playing_image);
-	g_object_ref (icon->priv->not_playing_image);
-
-	theme = gtk_icon_theme_get_default ();
-
-	gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &size, NULL);
-	icon->priv->app_pixbuf = gtk_icon_theme_load_icon (theme,
-							   RB_APP_ICON,
-							   size,
-							   0,
-							   NULL);
-
-	gtk_container_add (GTK_CONTAINER (icon->priv->ebox), icon->priv->not_playing_image);
-
-	gtk_container_add (GTK_CONTAINER (icon), icon->priv->ebox);
-	gtk_widget_show_all (GTK_WIDGET (icon->priv->ebox));
-}
-
-static GObject *
-rb_tray_icon_constructor (GType type, guint n_construct_properties,
-			  GObjectConstructParam *construct_properties)
-{
-	RBTrayIcon *tray;
-	RBTrayIconClass *klass;
-
-	klass = RB_TRAY_ICON_CLASS (g_type_class_peek (RB_TYPE_TRAY_ICON));
-
-	tray = RB_TRAY_ICON (G_OBJECT_CLASS (rb_tray_icon_parent_class)->constructor
-				(type, n_construct_properties,
-				 construct_properties));
-
-#ifdef HAVE_NOTIFY
-	tray->priv->show_notifications = eel_gconf_get_boolean (CONF_UI_SHOW_NOTIFICATIONS);
-#endif
-
-	tray->priv->actiongroup = gtk_action_group_new ("TrayActions");
-	gtk_action_group_set_translation_domain (tray->priv->actiongroup,
-						 GETTEXT_PACKAGE);
-	gtk_action_group_add_toggle_actions (tray->priv->actiongroup,
-					     rb_tray_icon_toggle_entries,
-					     rb_tray_icon_n_toggle_entries,
-					     tray);
-	rb_tray_icon_sync_action (NULL, FALSE, tray);
-
-	gtk_ui_manager_insert_action_group (tray->priv->ui_manager, tray->priv->actiongroup, 0);
-
-	return G_OBJECT (tray);
-}
-
-static void
-rb_tray_icon_dispose (GObject *object)
-{
-	RBTrayIcon *tray;
-
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (RB_IS_TRAY_ICON (object));
-
-	tray = RB_TRAY_ICON (object);
-
-	g_return_if_fail (tray->priv != NULL);
-
-	if (tray->priv->shell_player != NULL) {
-		g_object_unref (tray->priv->shell_player);
-		tray->priv->shell_player = NULL;
-	}
-
-	if (tray->priv->playing_image != NULL) {
-		g_object_unref (tray->priv->playing_image);
-		tray->priv->playing_image = NULL;
-	}
-
-	if (tray->priv->not_playing_image != NULL) {
-		g_object_unref (tray->priv->not_playing_image);
-		tray->priv->not_playing_image = NULL;
-	}
-
-	if (tray->priv->actiongroup != NULL) {
-		if (tray->priv->ui_manager != NULL) {
-			gtk_ui_manager_remove_action_group (tray->priv->ui_manager,
-							    tray->priv->actiongroup);
-		}
-		g_object_unref (tray->priv->actiongroup);
-		tray->priv->actiongroup = NULL;
-	}
-
-	if (tray->priv->pixbuf != NULL) {
-		g_object_unref (tray->priv->pixbuf);
-		tray->priv->pixbuf = NULL;
-	}
-
-	if (tray->priv->app_pixbuf != NULL) {
-		g_object_unref (tray->priv->app_pixbuf);
-		tray->priv->app_pixbuf = NULL;
-	}
-
-	G_OBJECT_CLASS (rb_tray_icon_parent_class)->dispose (object);
-}
-
-static void
-rb_tray_icon_finalize (GObject *object)
-{
-	RBTrayIcon *tray;
-
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (RB_IS_TRAY_ICON (object));
-
-	tray = RB_TRAY_ICON (object);
-
-	rb_debug ("tray icon %p finalizing", object);
-
-	g_return_if_fail (tray->priv != NULL);
-
-	if (tray->priv->tooltip_unsuppress_id > 0)
-		g_source_remove (tray->priv->tooltip_unsuppress_id);
-
-	G_OBJECT_CLASS (rb_tray_icon_parent_class)->finalize (object);
-}
-
-static void
-rb_tray_icon_sync_action (RBShell *shell, gboolean visible, RBTrayIcon *tray)
-{
-	GtkAction *action;
-
-	if ((tray->priv->actiongroup != NULL) && (tray->priv->shell != NULL)) {
-		gboolean visible;
-
-		action = gtk_action_group_get_action (tray->priv->actiongroup,
-						      "TrayShowWindow");
-		g_object_get (tray->priv->shell, "visibility", &visible, NULL);
-		gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
-
-		action = gtk_action_group_get_action (tray->priv->actiongroup,
-						      "TrayShowNotifications");
-#ifdef HAVE_NOTIFY
-		gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
-					      tray->priv->show_notifications);
-#else
-		gtk_action_set_visible (action, FALSE);
-#endif
-	}
-}
-
-static void
-rb_tray_icon_playing_changed_cb (RBShellPlayer *player, gboolean playing, RBTrayIcon *tray)
-{
-	GtkWidget *image;
-
-	if (playing)
-		image = tray->priv->playing_image;
-	else
-		image = tray->priv->not_playing_image;
-
-	gtk_container_remove (GTK_CONTAINER (tray->priv->ebox),
-			      gtk_bin_get_child (GTK_BIN (tray->priv->ebox)));
-	gtk_container_add (GTK_CONTAINER (tray->priv->ebox), image);
-	gtk_widget_show_all (GTK_WIDGET (tray->priv->ebox));
-}
-
-static void
-rb_tray_icon_set_property (GObject *object,
-			   guint prop_id,
-			   const GValue *value,
-			   GParamSpec *pspec)
-{
-	RBTrayIcon *tray = RB_TRAY_ICON (object);
-
-	switch (prop_id)
-	{
-	case PROP_SHELL:
-		tray->priv->shell = g_value_get_object (value);
-		g_signal_connect_object (G_OBJECT (tray->priv->shell),
-					 "visibility_changed",
-					 G_CALLBACK (rb_tray_icon_sync_action),
-					 tray, 0);
-		g_object_get (tray->priv->shell,
-			      "shell-player", &tray->priv->shell_player,
-			      NULL);
-		g_signal_connect_object (tray->priv->shell_player,
-					 "playing-changed",
-					 G_CALLBACK (rb_tray_icon_playing_changed_cb),
-					 tray, 0);
-		rb_tray_icon_sync_action (NULL, FALSE, tray);
-		break;
-	case PROP_UI_MANAGER:
-		tray->priv->ui_manager = g_value_get_object (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-rb_tray_icon_get_property (GObject *object,
-			      guint prop_id,
-			      GValue *value,
-			      GParamSpec *pspec)
-{
-	RBTrayIcon *tray = RB_TRAY_ICON (object);
-
-	switch (prop_id)
-	{
-	case PROP_SHELL:
-		g_value_set_object (value, tray->priv->shell);
-		break;
-	case PROP_UI_MANAGER:
-		g_value_set_object (value, tray->priv->ui_manager);
-		break;
-	case PROP_ACTION_GROUP:
-		g_value_set_object (value, tray->priv->actiongroup);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-/**
- * rb_tray_icon_new:
- * @mgr: the #GtkUIManager
- * @shell: the #RBShell
- * 
- * Return value: the #RBTrayIcon
- */
-RBTrayIcon *
-rb_tray_icon_new (GtkUIManager *mgr,
-		  RBShell *shell)
-{
-	return g_object_new (RB_TYPE_TRAY_ICON,
-			     "title", "Rhythmbox tray icon",
-			     "ui-manager", mgr,
-			     "shell", shell,
-			     NULL);
-}
-
-static void
-tray_popup_position_menu (GtkMenu *menu,
-			  int *x,
-			  int *y,
-			  gboolean *push_in,
-			  gpointer user_data)
-{
-        GtkWidget *widget;
-        GtkRequisition requisition;
-        gint menu_xpos;
-        gint menu_ypos;
-
-        widget = GTK_WIDGET (user_data);
-
-        gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
-
-        gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
-
-        menu_xpos += widget->allocation.x;
-        menu_ypos += widget->allocation.y;
-
-	if (menu_ypos > gdk_screen_get_height (gtk_widget_get_screen (widget)) / 2)
-		menu_ypos -= requisition.height + widget->style->ythickness;
-	else
-		menu_ypos += widget->allocation.height + widget->style->ythickness;
-
-        *x = menu_xpos;
-        *y = menu_ypos;
-        *push_in = TRUE;
-}
-
-static void
-rb_tray_icon_button_press_event_cb (GtkWidget *ebox, GdkEventButton *event,
-				    RBTrayIcon *icon)
-{
-	GtkWidget *popup;
-
-	/* filter out double, triple clicks */
-	if (event->type != GDK_BUTTON_PRESS)
-		return;
-
-	rb_debug ("tray button press");
-
-	switch (event->button) {
-	case 1:
-		rb_shell_toggle_visibility (icon->priv->shell);
-		break;
-	case 2:
-		rb_shell_player_playpause (icon->priv->shell_player, FALSE, NULL);
-		break;
-	case 3:
-		popup = gtk_ui_manager_get_widget (GTK_UI_MANAGER (icon->priv->ui_manager),
-						   "/RhythmboxTrayPopup");
-		gtk_menu_set_screen (GTK_MENU (popup), gtk_widget_get_screen (GTK_WIDGET (icon)));
-		gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
-				tray_popup_position_menu, ebox, 2,
-				gtk_get_current_event_time ());
-		break;
-	}
-}
-
-static void
-rb_tray_icon_scroll_event_cb (GtkWidget *ebox, GdkEvent *event,
-				    RBTrayIcon *icon)
-{
-	gdouble adjust;
-
-	switch (event->scroll.direction) {
-	case GDK_SCROLL_UP:
-		adjust = 0.02;
-		break;
-	case GDK_SCROLL_DOWN:
-		adjust = -0.02;
-		break;
-	default:
-		return;
-	}
-
-	rb_shell_player_set_volume_relative (icon->priv->shell_player, adjust, NULL);
-}
-
-static void
-rb_tray_icon_drop_cb (GtkWidget *widget,
-		      GdkDragContext *context,
-		      gint x,
-		      gint y,
-		      GtkSelectionData *data,
-		      guint info,
-		      guint time,
-		      RBTrayIcon *icon)
-{
-	GList *list, *i;
-	GtkTargetList *tlist;
-	gboolean ret;
-
-	tlist = gtk_target_list_new (target_uri, 1);
-	ret = (gtk_drag_dest_find_target (widget, context, tlist) != GDK_NONE);
-	gtk_target_list_unref (tlist);
-
-	if (ret == FALSE)
-		return;
-
-	list = rb_uri_list_parse ((char *) data->data);
-
-	if (list == NULL) {
-		gtk_drag_finish (context, FALSE, FALSE, time);
-		return;
-	}
-
-	for (i = list; i != NULL; i = i->next) {
-		char *uri = i->data;
-		if (uri != NULL)
-			rb_shell_load_uri (icon->priv->shell, uri, FALSE, NULL);
-
-		g_free (uri);
-	}
-
-	g_list_free (list);
-
-	gtk_drag_finish (context, TRUE, FALSE, time);
-}
-
-static void
-rb_tray_icon_show_window_changed_cb (GtkAction *action,
-				     RBTrayIcon *icon)
-{
-	rb_debug ("show window clicked for %p", icon);
-	g_object_set (G_OBJECT (icon->priv->shell),
-		      "visibility", gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)),
-		      NULL);
-}
-
-static void
-rb_tray_icon_show_notifications_changed_cb (GtkAction *action,
-					    RBTrayIcon *icon)
-{
-	rb_debug ("show notifications clicked for %p", icon);
-	icon->priv->show_notifications = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
-	eel_gconf_set_boolean (CONF_UI_SHOW_NOTIFICATIONS, icon->priv->show_notifications);
-}
-
-/**
- * rb_tray_icon_get_geom:
- * @icon: the #RBTrayIcon
- * @x: returns the x position of the tray icon
- * @y: returns the y position of the tray icon
- * @width: returns the width of the tray icon
- * @height: returns the height of the tray icon
- *
- * Retrieves the current position and size of the tray icon.
- */
-void
-rb_tray_icon_get_geom (RBTrayIcon *icon, int *x, int *y, int *width, int *height)
-{
-	GtkWidget *widget;
-	GtkRequisition requisition;
-
-	widget = GTK_WIDGET (icon->priv->ebox);
-
-	gtk_widget_size_request (widget, &requisition);
-
-	gdk_window_get_origin (widget->window, x, y);
-
-	*width = widget->allocation.x;
-	*height = widget->allocation.y;
-}
-
-static void
-rb_tray_icon_update_tooltip_visibility (RBTrayIcon *icon)
-{
-	gtk_widget_trigger_tooltip_query (GTK_WIDGET (icon));
-}
-
-/**
- * rb_tray_icon_set_tooltip_primary_text:
- * @icon: the #RBTrayIcon
- * @primary_text: the new primary text
- *
- * Updates the primary (large) text in the tray icon.
- */
-void
-rb_tray_icon_set_tooltip_primary_text (RBTrayIcon *icon,
-				       const char *primary_text)
-{
-	g_free (icon->priv->primary_text);
-	icon->priv->primary_text = g_strdup (primary_text);
-
-	gtk_widget_trigger_tooltip_query (GTK_WIDGET (icon));
-}
-
-
-
-/**
- * rb_tray_icon_set_tooltip_icon:
- * @icon: the #RBTrayIcon
- * @pixbuf: a #GdkPixbuf to display as the icon in the tooltip
- *
- * Updates the icon in the tooltip.
- */
-void
-rb_tray_icon_set_tooltip_icon (RBTrayIcon *icon, GdkPixbuf *pixbuf)
-{
-	if (icon->priv->pixbuf != NULL) {
-		g_object_unref (icon->priv->pixbuf);
-		icon->priv->pixbuf = NULL;
-	}
-
-	if (pixbuf != NULL) {
-		/* create a copy of the image with a black border */
-		int w = gdk_pixbuf_get_width (pixbuf);
-		int h = gdk_pixbuf_get_height (pixbuf);
-		icon->priv->pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pixbuf),
-						     gdk_pixbuf_get_has_alpha (pixbuf),
-						     gdk_pixbuf_get_bits_per_sample (pixbuf),
-						     w + (TOOLTIP_IMAGE_BORDER_WIDTH*2),
-						     h + (TOOLTIP_IMAGE_BORDER_WIDTH*2));
-		gdk_pixbuf_fill (icon->priv->pixbuf, 0xff);		/* opaque black */
-		gdk_pixbuf_copy_area (pixbuf,
-				      0, 0, w, h,
-				      icon->priv->pixbuf,
-				      TOOLTIP_IMAGE_BORDER_WIDTH,
-				      TOOLTIP_IMAGE_BORDER_WIDTH);
-	}
-
-	gtk_widget_trigger_tooltip_query (GTK_WIDGET (icon));
-}
-
-/**
- * rb_tray_icon_set_tooltip_secondary_markup:
- * @icon: the #RBTrayIcon
- * @secondary_markup: markup text to display as the secondary text in the toolip
- *
- * Updates the secondary text in the tooltip.  The secondary text can contain
- * simple markup.
- */
-void
-rb_tray_icon_set_tooltip_secondary_markup (RBTrayIcon *icon,
-					   const char *secondary_markup)
-{
-	g_free (icon->priv->secondary_markup);
-	icon->priv->secondary_markup = g_strdup (secondary_markup);
-
-	gtk_widget_trigger_tooltip_query (GTK_WIDGET (icon));
-}
-
-/**
- * rb_tray_icon_notify:
- * @icon: the #RBTrayIcon
- * @timeout: how long the notification should be displayed (in milliseconds)
- * @primary_markup: primary markup to display in the notification
- * @pixbuf: #GdkPixbuf to display as the image in the notification
- * @secondary_markup: secondary markup to display in the notification
- * @requested: if %TRUE, the notification was directly requested by the user
- *
- * Displays a notification bubble attached to the tray icon.  If the user has
- * disabled notifications, the notification is only displayed if @requested
- * is %TRUE.
- */
-void
-rb_tray_icon_notify (RBTrayIcon *icon,
-		     guint timeout,
-		     const char *primary_markup,
-		     GdkPixbuf *pixbuf,
-		     const char *secondary_markup,
-		     gboolean requested)
-{
-	if (!egg_tray_icon_have_manager (EGG_TRAY_ICON (icon))) {
-		rb_debug ("not showing notification: %s", primary_markup);
-		return;
-	}
-	if ((requested || icon->priv->show_notifications) == FALSE) {
-		rb_debug ("ignoring notification: %s", primary_markup);
-		return;
-	}
-
-	rb_debug ("doing notify: %s", primary_markup);
-	if (timeout > 0)
-		rb_tray_icon_suppress_tooltips (icon, timeout);
-	egg_tray_icon_notify (EGG_TRAY_ICON (icon), timeout,
-			      primary_markup, pixbuf, secondary_markup);
-}
-
-/**
- * rb_tray_icon_cancel_notify:
- * @icon: the #RBTrayIcon
- *
- * Cancels any existing notification bubble.
- */
-void
-rb_tray_icon_cancel_notify (RBTrayIcon *icon)
-{
-	egg_tray_icon_cancel_message (EGG_TRAY_ICON (icon), 1);
-}
-
-static gboolean
-tray_icon_tooltip_cb (GtkWidget  *widget,
-		      gint        x,
-		      gint        y,
-		      gboolean    keyboard_tooltip,
-		      GtkTooltip *tooltip,
-		      RBTrayIcon *icon)
-{
-	char *esc_primary;
-	char *markup;
-
-	if (icon->priv->tooltips_suppressed)
-		return FALSE;
-
-	if (icon->priv->pixbuf != NULL) {
-		gtk_tooltip_set_icon (tooltip, icon->priv->pixbuf);
-	} else {
-		gtk_tooltip_set_icon (tooltip, icon->priv->app_pixbuf);
-	}
-
-	if (icon->priv->primary_text != NULL) {
-		esc_primary = g_markup_escape_text (icon->priv->primary_text, -1);
-	} else {
-		esc_primary = g_markup_escape_text (TRAY_ICON_DEFAULT_TOOLTIP, -1);
-	}
-
-	if (icon->priv->secondary_markup != NULL) {
-		markup = g_strdup_printf ("<big><b>%s</b></big>\n\n%s",
-					  esc_primary,
-					  icon->priv->secondary_markup);
-	} else {
-		markup = g_strdup_printf ("<big><b>%s</b></big>", esc_primary);
-	}
-
-	gtk_tooltip_set_markup (tooltip, markup);
-
-	g_free (esc_primary);
-	g_free (markup);
-
-	return TRUE;
-}
-
-static gboolean
-rb_tray_icon_unsuppress_cb (RBTrayIcon *icon)
-{
-	gdk_threads_enter ();
-	icon->priv->tooltips_suppressed = FALSE;
-	rb_tray_icon_update_tooltip_visibility (icon);
-	icon->priv->tooltip_unsuppress_id = 0;
-	gdk_threads_leave ();
-	return FALSE;
-}
-
-static void
-rb_tray_icon_suppress_tooltips (RBTrayIcon *icon, guint duration)
-{
-	g_return_if_fail (duration > 0);
-
-	icon->priv->tooltips_suppressed = TRUE;
-	rb_tray_icon_update_tooltip_visibility (icon);
-
-	if (icon->priv->tooltip_unsuppress_id > 0)
-		g_source_remove (icon->priv->tooltip_unsuppress_id);
-	icon->priv->tooltip_unsuppress_id = g_timeout_add (duration, (GSourceFunc) rb_tray_icon_unsuppress_cb, icon);
-}
-
diff --git a/shell/rb-tray-icon.h b/shell/rb-tray-icon.h
deleted file mode 100644
index bc01fec..0000000
--- a/shell/rb-tray-icon.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *  arch-tag: Header for Rhythmbox tray icon object
- *
- *  Copyright (C) 2003 Colin Walters <walters verbum org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The Rhythmbox authors hereby grant permission for non-GPL compatible
- *  GStreamer plugins to be used and distributed together with GStreamer
- *  and Rhythmbox. This permission is above and beyond the permissions granted
- *  by the GPL license by which Rhythmbox is covered. If you modify this code
- *  you may extend this exception to your version of the code, but you are not
- *  obligated to do so. If you do not wish to do so, delete this exception
- *  statement from your version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
- *
- */
-
-#include <gtk/gtk.h>
-#include "eggtrayicon.h"
-#include "rhythmdb.h"
-#include "rb-shell.h"
-
-#ifndef __RB_TRAY_ICON_H
-#define __RB_TRAY_ICON_H
-
-G_BEGIN_DECLS
-
-#define RB_TYPE_TRAY_ICON         (rb_tray_icon_get_type ())
-#define RB_TRAY_ICON(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_TRAY_ICON, RBTrayIcon))
-#define RB_TRAY_ICON_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_TRAY_ICON, RBTrayIconClass))
-#define RB_IS_TRAY_ICON(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_TRAY_ICON))
-#define RB_IS_TRAY_ICON_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_TRAY_ICON))
-#define RB_TRAY_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_TRAY_ICON, RBTrayIconClass))
-
-typedef struct _RBTrayIcon RBTrayIcon;
-typedef struct _RBTrayIconClass RBTrayIconClass;
-
-typedef struct RBTrayIconPrivate RBTrayIconPrivate;
-
-struct _RBTrayIcon
-{
-	EggTrayIcon parent;
-
-	RBTrayIconPrivate *priv;
-};
-
-struct _RBTrayIconClass
-{
-	EggTrayIconClass parent_class;
-};
-
-GType			rb_tray_icon_get_type	(void);
-
-RBTrayIcon *		rb_tray_icon_new	(GtkUIManager *mgr, RBShell *shell);
-
-void                    rb_tray_icon_get_geom   (RBTrayIcon *icon, int *x, int *y, int *width, int *height);
-
-void                    rb_tray_icon_notify     (RBTrayIcon *icon,
-						 guint timeout,
-						 const char *primary_markup,
-						 GdkPixbuf *pixbuf,
-						 const char *secondary_markup,
-						 gboolean requested);
-
-void                    rb_tray_icon_cancel_notify (RBTrayIcon *icon);
-
-void rb_tray_icon_set_tooltip_primary_text (RBTrayIcon *icon, const char *primary_text);
-void rb_tray_icon_set_tooltip_icon (RBTrayIcon *icon, GdkPixbuf *pixbuf);
-void rb_tray_icon_set_tooltip_secondary_markup (RBTrayIcon *icon, const char *secondary_markup);
-
-G_END_DECLS
-
-#endif /* __RB_TRAY_ICON_H */
diff --git a/sources/rb-podcast-source.c b/sources/rb-podcast-source.c
index 97745ce..73a4ed6 100644
--- a/sources/rb-podcast-source.c
+++ b/sources/rb-podcast-source.c
@@ -1742,11 +1742,13 @@ rb_podcast_source_start_download_cb (RBPodcastManager *pd,
 				     RBPodcastSource *source)
 {
 	RBShell *shell = rb_podcast_source_get_shell (source);
-	const gchar *podcast_name = rhythmdb_entry_get_string(entry, RHYTHMDB_PROP_TITLE);
+	char *podcast_name;
+
+	podcast_name = g_markup_escape_text (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE), -1);
+	rb_shell_notify_custom (shell, 4000, _("Downloading podcast"), podcast_name, NULL, FALSE);
 
-	rb_debug ("Start download");
-	rb_shell_hidden_notify (shell, 4000, _("Downloading podcast"), NULL, podcast_name, FALSE);
 	g_object_unref (shell);
+	g_free (podcast_name);
 }
 
 static void
@@ -1755,11 +1757,13 @@ rb_podcast_source_finish_download_cb (RBPodcastManager *pd,
 				      RBPodcastSource *source)
 {
 	RBShell *shell = rb_podcast_source_get_shell (source);
-	const gchar *podcast_name = rhythmdb_entry_get_string(entry, RHYTHMDB_PROP_TITLE);
+	char *podcast_name;
+
+	podcast_name = g_markup_escape_text (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE), -1);
+	rb_shell_notify_custom (shell, 4000, _("Finished downloading podcast"), podcast_name, NULL, FALSE);
 
-	rb_debug ("Finish download");
-	rb_shell_hidden_notify (shell, 4000, _("Finished downloading podcast"), NULL, podcast_name, FALSE);
 	g_object_unref (shell);
+	g_free (podcast_name);
 }
 
 static void
@@ -1768,11 +1772,13 @@ rb_podcast_source_feed_updates_available_cb (RBPodcastManager *pd,
 					     RBPodcastSource *source)
 {
 	RBShell *shell = rb_podcast_source_get_shell (source);
-	const gchar *podcast_name = rhythmdb_entry_get_string(entry, RHYTHMDB_PROP_TITLE);
+	char *podcast_name;
+
+	podcast_name = g_markup_escape_text (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE), -1);
+	rb_shell_notify_custom (shell, 4000, _("New updates available from"), podcast_name, NULL, FALSE);
 
-	rb_debug ("Updates available");
-	rb_shell_hidden_notify (shell, 4000, _("New updates available from"), NULL, podcast_name, FALSE);
 	g_object_unref (shell);
+	g_free (podcast_name);
 
 }
 
diff --git a/sources/rb-streaming-source.c b/sources/rb-streaming-source.c
index d51dff9..364a7c1 100644
--- a/sources/rb-streaming-source.c
+++ b/sources/rb-streaming-source.c
@@ -353,9 +353,7 @@ emit_notification_cb (RBStreamingSource *source)
 	source->priv->emit_notify_id = 0;
 
 	g_object_get (G_OBJECT (source), "shell", &shell, NULL);
-	rb_shell_notify_playing_entry (shell,
-				       source->priv->playing_stream,
-				       FALSE);
+	rb_shell_do_notify (shell, FALSE, NULL);
 	g_object_unref (shell);
 
 	return FALSE;
diff --git a/widgets/Makefile.am b/widgets/Makefile.am
index 78eaac6..a989b1e 100644
--- a/widgets/Makefile.am
+++ b/widgets/Makefile.am
@@ -16,8 +16,6 @@ librbwidgets_la_SOURCES =				\
 	rb-search-entry.h				\
 	rb-header.c					\
 	rb-header.h					\
-	eggtrayicon.c					\
-	eggtrayicon.h					\
 	rb-dialog.c					\
 	rb-dialog.h					\
 	rb-cell-renderer-pixbuf.c			\
diff --git a/widgets/eggtrayicon.c b/widgets/eggtrayicon.c
deleted file mode 100644
index bf03cf2..0000000
--- a/widgets/eggtrayicon.c
+++ /dev/null
@@ -1,630 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* eggtrayicon.c
- * Copyright (C) 2002 Anders Carlsson <andersca gnu org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301  USA.
- */
-
-#include <config.h>
-#include <string.h>
-#include <libintl.h>
-
-#include "eggtrayicon.h"
-#include "rb-stock-icons.h"
-#include "rb-file-helpers.h"
-
-#include <gdkconfig.h>
-#include <gtk/gtk.h>
-#if defined (GDK_WINDOWING_X11)
-#include <gdk/gdkx.h>
-#include <X11/Xatom.h>
-#elif defined (GDK_WINDOWING_WIN32)
-#include <gdk/gdkwin32.h>
-#endif
-#ifdef HAVE_NOTIFY
-#include <libnotify/notify.h>
-#endif
-
-#ifndef EGG_COMPILATION
-#ifndef _
-#define _(x) dgettext (GETTEXT_PACKAGE, x)
-#define N_(x) x
-#endif
-#else
-#define _(x) x
-#define N_(x) x
-#endif
-
-#define SYSTEM_TRAY_REQUEST_DOCK    0
-#define SYSTEM_TRAY_BEGIN_MESSAGE   1
-#define SYSTEM_TRAY_CANCEL_MESSAGE  2
-
-#define SYSTEM_TRAY_ORIENTATION_HORZ 0
-#define SYSTEM_TRAY_ORIENTATION_VERT 1
-
-enum {
-  PROP_0,
-  PROP_ORIENTATION
-};
-
-#ifdef HAVE_NOTIFY
-struct _Notify {
-  NotifyNotification *handle;
-};
-#endif
-
-static GtkPlugClass *parent_class = NULL;
-
-static void egg_tray_icon_init (EggTrayIcon *icon);
-static void egg_tray_icon_class_init (EggTrayIconClass *klass);
-
-static void egg_tray_icon_get_property (GObject    *object,
-					guint       prop_id,
-					GValue     *value,
-					GParamSpec *pspec);
-
-static void egg_tray_icon_realize   (GtkWidget *widget);
-static void egg_tray_icon_unrealize (GtkWidget *widget);
-
-static void egg_tray_icon_add (GtkContainer *container,
-			       GtkWidget    *widget);
-
-#ifdef GDK_WINDOWING_X11
-static void egg_tray_icon_update_manager_window    (EggTrayIcon *icon,
-						    gboolean     dock_if_realized);
-static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon);
-#endif
-
-GType
-egg_tray_icon_get_type (void)
-{
-  static GType our_type = 0;
-
-  if (our_type == 0)
-    {
-      static const GTypeInfo our_info =
-      {
-	sizeof (EggTrayIconClass),
-	(GBaseInitFunc) NULL,
-	(GBaseFinalizeFunc) NULL,
-	(GClassInitFunc) egg_tray_icon_class_init,
-	NULL, /* class_finalize */
-	NULL, /* class_data */
-	sizeof (EggTrayIcon),
-	0,    /* n_preallocs */
-	(GInstanceInitFunc) egg_tray_icon_init
-      };
-
-      our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
-    }
-
-  return our_type;
-}
-
-static void
-egg_tray_icon_init (EggTrayIcon *icon)
-{
-  icon->stamp = 1;
-  icon->orientation = GTK_ORIENTATION_HORIZONTAL;
-#ifdef HAVE_NOTIFY
-  icon->notify = g_new0 (Notify, 1);
-#endif
-  gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
-}
-
-static void
-egg_tray_icon_class_init (EggTrayIconClass *klass)
-{
-  GObjectClass *gobject_class = (GObjectClass *)klass;
-  GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
-  GtkContainerClass *container_class = (GtkContainerClass *)klass;
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class->get_property = egg_tray_icon_get_property;
-
-  widget_class->realize   = egg_tray_icon_realize;
-  widget_class->unrealize = egg_tray_icon_unrealize;
-
-  container_class->add = egg_tray_icon_add;
-
-  g_object_class_install_property (gobject_class,
-				   PROP_ORIENTATION,
-				   g_param_spec_enum ("orientation",
-						      _("Orientation"),
-						      _("The orientation of the tray."),
-						      GTK_TYPE_ORIENTATION,
-						      GTK_ORIENTATION_HORIZONTAL,
-						      G_PARAM_READABLE));
-
-#if defined (GDK_WINDOWING_X11)
-  /* Nothing */
-#elif defined (GDK_WINDOWING_WIN32)
-  g_warning ("Port eggtrayicon to Win32");
-#else
-  g_warning ("Port eggtrayicon to this GTK+ backend");
-#endif
-}
-
-static void
-egg_tray_icon_get_property (GObject    *object,
-			    guint       prop_id,
-			    GValue     *value,
-			    GParamSpec *pspec)
-{
-  EggTrayIcon *icon = EGG_TRAY_ICON (object);
-
-  switch (prop_id)
-    {
-    case PROP_ORIENTATION:
-      g_value_set_enum (value, icon->orientation);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-#ifdef GDK_WINDOWING_X11
-
-static void
-egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
-{
-  Display *xdisplay;
-  Atom type;
-  int format;
-  union {
-	gulong *prop;
-	guchar *prop_ch;
-  } prop = { NULL };
-  gulong nitems;
-  gulong bytes_after;
-  int error, result;
-
-  g_assert (icon->manager_window != None);
-
-  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-
-  gdk_error_trap_push ();
-  type = None;
-  result = XGetWindowProperty (xdisplay,
-			       icon->manager_window,
-			       icon->orientation_atom,
-			       0, G_MAXLONG, FALSE,
-			       XA_CARDINAL,
-			       &type, &format, &nitems,
-			       &bytes_after, &(prop.prop_ch));
-  error = gdk_error_trap_pop ();
-
-  if (error || result != Success)
-    return;
-
-  if (type == XA_CARDINAL)
-    {
-      GtkOrientation orientation;
-
-      orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
-					GTK_ORIENTATION_HORIZONTAL :
-					GTK_ORIENTATION_VERTICAL;
-
-      if (icon->orientation != orientation)
-	{
-	  icon->orientation = orientation;
-
-	  g_object_notify (G_OBJECT (icon), "orientation");
-	}
-    }
-
-  if (prop.prop)
-    XFree (prop.prop);
-}
-
-static GdkFilterReturn
-egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
-{
-  EggTrayIcon *icon = user_data;
-  XEvent *xev = (XEvent *)xevent;
-
-  if (xev->xany.type == ClientMessage &&
-      xev->xclient.message_type == icon->manager_atom &&
-      xev->xclient.data.l[1] == icon->selection_atom)
-    {
-      egg_tray_icon_update_manager_window (icon, TRUE);
-    }
-  else if (xev->xany.window == icon->manager_window)
-    {
-      if (xev->xany.type == PropertyNotify &&
-	  xev->xproperty.atom == icon->orientation_atom)
-	{
-	  egg_tray_icon_get_orientation_property (icon);
-	}
-      if (xev->xany.type == DestroyNotify)
-	{
-	  egg_tray_icon_manager_window_destroyed (icon);
-	}
-    }
-  return GDK_FILTER_CONTINUE;
-}
-
-#endif
-
-static void
-egg_tray_icon_unrealize (GtkWidget *widget)
-{
-#ifdef GDK_WINDOWING_X11
-  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
-  GdkWindow *root_window;
-
-  if (icon->manager_window != None)
-    {
-      GdkWindow *gdkwin;
-
-      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
-                                              icon->manager_window);
-
-      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
-    }
-
-  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
-
-  gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
-
-  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
-    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
-#endif
-
-#ifdef HAVE_NOTIFY
-
-  if (EGG_TRAY_ICON (widget)->notify->handle) {
-    notify_notification_close (EGG_TRAY_ICON (widget)->notify->handle, NULL);
-  }
-
-  g_free (EGG_TRAY_ICON (widget)->notify);
-#endif
-}
-
-#ifdef GDK_WINDOWING_X11
-
-static void
-egg_tray_icon_send_manager_message (EggTrayIcon *icon,
-				    long         message,
-				    Window       window,
-				    long         data1,
-				    long         data2,
-				    long         data3)
-{
-  XClientMessageEvent ev;
-  Display *display;
-
-  ev.type = ClientMessage;
-  ev.window = window;
-  ev.message_type = icon->system_tray_opcode_atom;
-  ev.format = 32;
-  ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
-  ev.data.l[1] = message;
-  ev.data.l[2] = data1;
-  ev.data.l[3] = data2;
-  ev.data.l[4] = data3;
-
-  display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-
-  gdk_error_trap_push ();
-  XSendEvent (display,
-	      icon->manager_window, False, NoEventMask, (XEvent *)&ev);
-  XSync (display, False);
-  gdk_error_trap_pop ();
-}
-
-static void
-egg_tray_icon_send_dock_request (EggTrayIcon *icon)
-{
-  egg_tray_icon_send_manager_message (icon,
-				      SYSTEM_TRAY_REQUEST_DOCK,
-				      icon->manager_window,
-				      gtk_plug_get_id (GTK_PLUG (icon)),
-				      0, 0);
-}
-
-static void
-egg_tray_icon_update_manager_window (EggTrayIcon *icon,
-				     gboolean     dock_if_realized)
-{
-  Display *xdisplay;
-
-  if (icon->manager_window != None)
-    return;
-
-  xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
-
-  XGrabServer (xdisplay);
-
-  icon->manager_window = XGetSelectionOwner (xdisplay,
-					     icon->selection_atom);
-
-  if (icon->manager_window != None)
-    XSelectInput (xdisplay,
-		  icon->manager_window, StructureNotifyMask|PropertyChangeMask);
-
-  XUngrabServer (xdisplay);
-  XFlush (xdisplay);
-
-  if (icon->manager_window != None)
-    {
-      GdkWindow *gdkwin;
-
-      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
-					      icon->manager_window);
-
-      gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
-
-      if (dock_if_realized && GTK_WIDGET_REALIZED (icon))
-	egg_tray_icon_send_dock_request (icon);
-
-      egg_tray_icon_get_orientation_property (icon);
-    }
-}
-
-static gboolean
-transparent_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
-{
-  gdk_window_clear_area (widget->window, event->area.x, event->area.y,
-			 event->area.width, event->area.height);
-  return FALSE;
-}
-
-static void
-make_transparent_again (GtkWidget *widget, GtkStyle *previous_style,
-			gpointer user_data)
-{
-  gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
-}
-
-static void
-make_transparent (GtkWidget *widget, gpointer user_data)
-{
-  if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget))
-    return;
-
-  gtk_widget_set_app_paintable (widget, TRUE);
-  gtk_widget_set_double_buffered (widget, FALSE);
-  gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
-  g_signal_connect (widget, "expose_event",
-		    G_CALLBACK (transparent_expose_event), NULL);
-  g_signal_connect_after (widget, "style_set",
-			  G_CALLBACK (make_transparent_again), NULL);
-}	
-
-static void
-egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon)
-{
-  GdkWindow *gdkwin;
-
-  g_return_if_fail (icon->manager_window != None);
-
-  gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
-					  icon->manager_window);
-
-  gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
-
-  icon->manager_window = None;
-
-  egg_tray_icon_update_manager_window (icon, TRUE);
-}
-
-#endif
-
-gboolean
-egg_tray_icon_have_manager (EggTrayIcon *icon)
-{
-  GtkPlug * plug = GTK_PLUG (icon);
-
-  if (plug->socket_window)
-    return TRUE;
-  else
-    return FALSE;
-}
-
-static void
-egg_tray_icon_realize (GtkWidget *widget)
-{
-#ifdef GDK_WINDOWING_X11
-  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
-  GdkScreen *screen;
-  GdkDisplay *display;
-  Display *xdisplay;
-  char buffer[256];
-  GdkWindow *root_window;
-
-  if (GTK_WIDGET_CLASS (parent_class)->realize)
-    GTK_WIDGET_CLASS (parent_class)->realize (widget);
-
-  make_transparent (widget, NULL);
-
-  screen = gtk_widget_get_screen (widget);
-  display = gdk_screen_get_display (screen);
-  xdisplay = gdk_x11_display_get_xdisplay (display);
-
-  /* Now see if there's a manager window around */
-  g_snprintf (buffer, sizeof (buffer),
-	      "_NET_SYSTEM_TRAY_S%d",
-	      gdk_screen_get_number (screen));
-
-  icon->selection_atom = XInternAtom (xdisplay, buffer, False);
-
-  icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
-
-  icon->system_tray_opcode_atom = XInternAtom (xdisplay,
-						   "_NET_SYSTEM_TRAY_OPCODE",
-						   False);
-
-  icon->orientation_atom = XInternAtom (xdisplay,
-					"_NET_SYSTEM_TRAY_ORIENTATION",
-					False);
-
-  egg_tray_icon_update_manager_window (icon, FALSE);
-  egg_tray_icon_send_dock_request (icon);
-
-  root_window = gdk_screen_get_root_window (screen);
-
-  /* Add a root window filter so that we get changes on MANAGER */
-  gdk_window_add_filter (root_window,
-			 egg_tray_icon_manager_filter, icon);
-#endif
-}
-
-static void
-egg_tray_icon_add (GtkContainer *container, GtkWidget *widget)
-{
-  g_signal_connect (widget, "realize",
-		    G_CALLBACK (make_transparent), NULL);
-  GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
-}
-
-EggTrayIcon *
-egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
-{
-  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-
-  return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
-}
-
-EggTrayIcon*
-egg_tray_icon_new (const gchar *name)
-{
-  return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
-}
-
-guint
-egg_tray_icon_send_message (EggTrayIcon *icon,
-			    gint         timeout,
-			    const gchar *message_markup,
-			    gint         len)
-{
-  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
-  g_return_val_if_fail (timeout >= 0, 0);
-  g_return_val_if_fail (message_markup != NULL, 0);
-
-#ifdef HAVE_NOTIFY
-  egg_tray_icon_notify (icon, timeout, _("Notification"), NULL, message_markup);
-#endif
-
-  return 1;
-}
-
-void
-egg_tray_icon_cancel_message (EggTrayIcon *icon,
-			      guint        id)
-{
-  g_return_if_fail (EGG_IS_TRAY_ICON (icon));
-
-#ifdef HAVE_NOTIFY
-  if (icon->notify->handle)
-  {
-    notify_notification_close (icon->notify->handle, NULL);
-  }
-#endif
-}
-
-GtkOrientation
-egg_tray_icon_get_orientation (EggTrayIcon *icon)
-{
-  g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
-
-  return icon->orientation;
-}
-
-void
-egg_tray_icon_notify (EggTrayIcon *icon,
-		      guint timeout,
-		      const char *primary_markup,
-		      GdkPixbuf *pixbuf,
-		      const char *secondary_markup)
-{
-#ifdef HAVE_NOTIFY
-  GtkRequisition size;
-  int x;
-  int y;
-
-  if (!notify_is_initted ())
-    if (!notify_init ("rhythmbox"))
-      return;
-
-  if (primary_markup == NULL)
-    {
-      primary_markup = "";
-    }
-  if (secondary_markup == NULL)
-    {
-      secondary_markup = "";
-    }
-
-  if (icon->notify->handle == NULL)
-    {
-      icon->notify->handle = notify_notification_new (primary_markup,
-						      secondary_markup,
-						      NULL,
-						      GTK_WIDGET (icon));
-    }
-  else
-    {
-      notify_notification_update (icon->notify->handle,
-				  primary_markup,
-				  secondary_markup,
-				  NULL);
-      notify_notification_attach_to_widget (icon->notify->handle,
-					    GTK_WIDGET (icon));
-    }
-
-  notify_notification_set_timeout (icon->notify->handle, timeout);
-
-  if (pixbuf == NULL)
-    {
-      GtkIconTheme *theme;
-      gint size;
-
-      theme = gtk_icon_theme_get_default ();
-      gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &size, NULL);
-      pixbuf = gtk_icon_theme_load_icon (theme,
-	  				 RB_APP_ICON,
-					 size,
-					 0,
-					 NULL);
-      if (pixbuf != NULL)
-	{
-	  notify_notification_set_icon_from_pixbuf (icon->notify->handle, pixbuf);
-	  g_object_unref (pixbuf);
-	}
-    }
-  else
-    {
-      notify_notification_set_icon_from_pixbuf (icon->notify->handle, pixbuf);
-    }
-
-  gdk_window_get_origin (GTK_WIDGET (icon)->window, &x, &y);
-  gtk_widget_size_request (GTK_WIDGET (icon), &size);
-  x += size.width / 2;
-  y += size.height;
-  notify_notification_set_hint_int32 (icon->notify->handle, "x", x);
-  notify_notification_set_hint_int32 (icon->notify->handle, "y", y);
-
-  if (! notify_notification_show (icon->notify->handle, NULL))
-    {
-      g_warning ("failed to send notification (%s)", primary_markup);
-    }
-
-  return;
-#endif
-}
diff --git a/widgets/eggtrayicon.h b/widgets/eggtrayicon.h
deleted file mode 100644
index 40d62a3..0000000
--- a/widgets/eggtrayicon.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* eggtrayicon.h
- * Copyright (C) 2002 Anders Carlsson <andersca gnu org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301  USA.
- */
-
-#ifndef __EGG_TRAY_ICON_H__
-#define __EGG_TRAY_ICON_H__
-
-#include <config.h>
-
-#include <gtk/gtk.h>
-#ifdef GDK_WINDOWING_X11
-#include <gdk/gdkx.h>
-#endif
-#ifdef HAVE_NOTIFY
-#include <libnotify/notify.h>
-#endif
-
-G_BEGIN_DECLS
-
-#define EGG_TYPE_TRAY_ICON		(egg_tray_icon_get_type ())
-#define EGG_TRAY_ICON(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon))
-#define EGG_TRAY_ICON_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
-#define EGG_IS_TRAY_ICON(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON))
-#define EGG_IS_TRAY_ICON_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON))
-#define EGG_TRAY_ICON_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
-
-typedef struct _EggTrayIcon	  EggTrayIcon;
-typedef struct _EggTrayIconClass  EggTrayIconClass;
-#ifdef HAVE_NOTIFY
-typedef struct _Notify		  Notify;
-#endif
-
-struct _EggTrayIcon
-{
-  GtkPlug parent_instance;
-
-  guint stamp;
-
-#ifdef GDK_WINDOWING_X11
-  Atom selection_atom;
-  Atom manager_atom;
-  Atom system_tray_opcode_atom;
-  Atom orientation_atom;
-  Window manager_window;
-#endif
-  GtkOrientation orientation;
-#ifdef HAVE_NOTIFY
-  Notify *notify;
-#endif
-};
-
-struct _EggTrayIconClass
-{
-  GtkPlugClass parent_class;
-};
-
-GType        egg_tray_icon_get_type       (void);
-
-EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen   *screen,
-					   const gchar *name);
-
-EggTrayIcon *egg_tray_icon_new            (const gchar *name);
-
-guint        egg_tray_icon_send_message   (EggTrayIcon *icon,
-					   gint         timeout,
-					   const char  *message_markup,
-					   gint         len);
-void         egg_tray_icon_cancel_message (EggTrayIcon *icon,
-					   guint        id);
-
-gboolean     egg_tray_icon_have_manager   (EggTrayIcon *icon);
-
-void 	     egg_tray_icon_notify         (EggTrayIcon *icon,
-					   guint timeout,
-					   const char *primary_markup,
-					   GdkPixbuf  *pixbuf,
-					   const char *secondary_markup);
-
-GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon);
-
-G_END_DECLS
-
-#endif /* __EGG_TRAY_ICON_H__ */
diff --git a/widgets/update-from-egg.sh b/widgets/update-from-egg.sh
deleted file mode 100644
index 19d31bd..0000000
--- a/widgets/update-from-egg.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-# arch-tag: Script to update copied widget files from libegg
-
-function die() {
-  echo $*
-  exit 1
-}
-
-if test -z "$EGGDIR"; then
-   echo "Must set EGGDIR"
-   exit 1
-fi
-
-if test -z "$EGGFILES"; then
-   echo "Must set EGGFILES"
-   exit 1
-fi
-
-for FILE in $EGGFILES; do
-  if cmp -s $EGGDIR/$FILE $FILE; then
-     echo "File $FILE is unchanged"
-  else
-     cp $EGGDIR/$FILE $FILE || die "Could not move $EGGDIR/$FILE to $FILE"
-     echo "Updated $FILE"
-  fi
-done



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