diff --git a/src/vte-private.h b/src/vte-private.h
index 6b5e0b3..c666338 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -339,6 +339,10 @@ struct _VteTerminalPrivate {
 	gboolean adjustment_changed_tag;
 	guint status_line_changed_pending;
 
+	/* Title changes pending. */
+	guint window_title_changed_pending;
+	guint icon_title_changed_pending;
+
 	/* Background images/"transparency". */
 	guint bg_update_pending;
 	gboolean bg_transparent;
diff --git a/src/vte.c b/src/vte.c
index 84ebea8..26486bd 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -7093,6 +7093,17 @@ #endif
 	}
 	terminal->pvt->has_fonts = FALSE;
 
+	/* cancel pending window updates */
+	if (terminal->pvt->window_title_changed_pending) {
+		g_source_remove (terminal->pvt->window_title_changed_pending);
+		terminal->pvt->window_title_changed_pending = VTE_INVALID_SOURCE;
+	}
+	if (terminal->pvt->icon_title_changed_pending) {
+		g_source_remove (terminal->pvt->icon_title_changed_pending);
+		terminal->pvt->icon_title_changed_pending = VTE_INVALID_SOURCE;
+	}
+
+
 	/* Unmap the widget if it hasn't been already. */
 	if (GTK_WIDGET_MAPPED(widget)) {
 		gtk_widget_unmap(widget);
diff --git a/src/vteseq.c b/src/vteseq.c
index aaeae57..220c6a2 100644
--- a/src/vteseq.c
+++ b/src/vteseq.c
@@ -132,7 +132,7 @@ #endif
 }
 
 /* Emit an "icon-title-changed" signal. */
-static void
+static gboolean
 vte_terminal_emit_icon_title_changed(VteTerminal *terminal)
 {
 #ifdef VTE_DEBUG
@@ -140,11 +140,27 @@ #ifdef VTE_DEBUG
 		g_printerr("Emitting `icon-title-changed'.\n");
 	}
 #endif
+	if (terminal->widget.window != NULL)
+		gdk_window_set_icon_name (terminal->widget.window,
+			       	terminal->icon_title);
+
 	g_signal_emit_by_name(terminal, "icon-title-changed");
+
+	terminal->pvt->icon_title_changed_pending = VTE_INVALID_SOURCE;
+	return FALSE;
+}
+static void
+vte_terminal_queue_icon_title_changed(VteTerminal *terminal)
+{
+	if (terminal->pvt->icon_title_changed_pending == VTE_INVALID_SOURCE) {
+		terminal->pvt->icon_title_changed_pending =
+			g_idle_add((GSourceFunc) vte_terminal_emit_icon_title_changed,
+					terminal);
+	}
 }
 
 /* Emit a "window-title-changed" signal. */
-static void
+static gboolean
 vte_terminal_emit_window_title_changed(VteTerminal *terminal)
 {
 #ifdef VTE_DEBUG
@@ -152,7 +168,23 @@ #ifdef VTE_DEBUG
 		g_printerr("Emitting `window-title-changed'.\n");
 	}
 #endif
+	if (terminal->widget.window != NULL)
+		gdk_window_set_title (terminal->widget.window,
+			       	terminal->window_title);
+
 	g_signal_emit_by_name(terminal, "window-title-changed");
+
+	terminal->pvt->icon_title_changed_pending = VTE_INVALID_SOURCE;
+	return FALSE;
+}
+static void
+vte_terminal_queue_window_title_changed(VteTerminal *terminal)
+{
+	if (terminal->pvt->window_title_changed_pending == VTE_INVALID_SOURCE) {
+		terminal->pvt->window_title_changed_pending =
+			g_idle_add((GSourceFunc) vte_terminal_emit_window_title_changed,
+					terminal);
+	}
 }
 
 /* Emit a "raise-window" signal. */
@@ -457,16 +489,12 @@ #endif
 			if (strcmp(signal, "window") == 0) {
 				g_free(terminal->window_title);
 				terminal->window_title = g_strdup(validated);
-				if (terminal->widget.window)
-					gdk_window_set_title (terminal->widget.window, validated);
-				vte_terminal_emit_window_title_changed(terminal);
+				vte_terminal_queue_window_title_changed(terminal);
 			} else
 			if (strcmp(signal, "icon") == 0) {
 				g_free (terminal->icon_title);
 				terminal->icon_title = g_strdup(validated);
-				if (terminal->widget.window)
-					gdk_window_set_icon_name (terminal->widget.window, validated);
-				vte_terminal_emit_icon_title_changed(terminal);
+				vte_terminal_queue_icon_title_changed(terminal);
 			}
 			g_free(validated);
 			g_free(title);
