diff --git a/src/vte-private.h b/src/vte-private.h
index fc6a570..83862ed 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -102,6 +102,7 @@ G_BEGIN_DECLS
 #define VTE_DISPLAY_TIMEOUT		10
 #define VTE_UPDATE_TIMEOUT		15
 #define VTE_UPDATE_REPEAT_TIMEOUT	30
+#define VTE_VISIBLE_BELL_DURATION       80
 #define VTE_MAX_PROCESS_TIME		100
 #define VTE_CELL_BBOX_SLACK		1
 
@@ -298,6 +299,9 @@ struct _VteTerminalPrivate {
 	gboolean cursor_visible;
 	gboolean has_focus;               /* is the terminal window focused */
 
+        /* Visible bell's state. */
+        guint visible_bell_tag;           /* timeout ID for stopping the bell */
+
 	/* Input device options. */
         gboolean input_enabled;
 	time_t last_keypress_time;
@@ -433,8 +437,6 @@ gboolean _vte_terminal_get_tabstop(VteTerminal *terminal, int column);
 void _vte_terminal_set_tabstop(VteTerminal *terminal, int column);
 void _vte_terminal_update_insert_delta(VteTerminal *terminal);
 void _vte_terminal_cleanup_fragments(VteTerminal *terminal, long start, long end);
-void _vte_terminal_audible_beep(VteTerminal *terminal);
-void _vte_terminal_visible_beep(VteTerminal *terminal);
 void _vte_terminal_beep(VteTerminal *terminal);
 PangoColor *_vte_terminal_get_color(const VteTerminal *terminal, int idx);
 void _vte_terminal_set_color_internal(VteTerminal *terminal,
diff --git a/src/vte.c b/src/vte.c
index 642e8fa..62a8234 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -126,6 +126,10 @@ static void remove_update_timeout (VteTerminal *terminal);
 static void reset_update_regions (VteTerminal *terminal);
 static void vte_terminal_set_cursor_blinks_internal(VteTerminal *terminal, gboolean blink);
 static void _vte_check_cursor_blink(VteTerminal *terminal);
+static void _vte_terminal_audible_beep(VteTerminal *terminal);
+static void remove_visible_bell_timeout (VteTerminal *terminal);
+static gboolean stop_visible_beep (VteTerminal *terminal);
+static void _vte_terminal_visible_beep(VteTerminal *terminal);
 
 static gboolean process_timeout (gpointer data);
 static gboolean update_timeout (gpointer data);
@@ -4649,7 +4653,7 @@ _vte_check_cursor_blink(VteTerminal *terminal)
 		remove_cursor_timeout(terminal);
 }
 
-void
+static void
 _vte_terminal_audible_beep(VteTerminal *terminal)
 {
 	GdkDisplay *display;
@@ -4659,15 +4663,46 @@ _vte_terminal_audible_beep(VteTerminal *terminal)
 	gdk_display_beep(display);
 }
 
-void
+static void
+remove_visible_bell_timeout (VteTerminal *terminal)
+{
+        if (terminal->pvt->visible_bell_tag == 0)
+                return; /* already removed */
+
+        g_source_remove (terminal->pvt->visible_bell);
+        terminal->pvt->visible_bell_tag = 0;
+}
+
+static gboolean
+stop_visible_beep (VteTerminal *terminal)
+{
+        if (G_LIKELY (gtk_widget_get_realized (&terminal->widget) && gtk_widget_get_mapped (&terminal->widget))) {
+                /* Force the repaint, max delay of UPDATE_REPEAT_TIMEOUT */
+                _vte_invalidate_all (terminal);
+        }
+        terminal->pvt->visible_bell_tag = 0;
+        return FALSE;
+}
+
+static void
 _vte_terminal_visible_beep(VteTerminal *terminal)
 {
 	GtkWidget *widget = &terminal->widget;
 
-	if (gtk_widget_get_realized (widget)) {
+        if (G_UNLIKELY (!gtk_widget_get_realized (widget) || !gtk_widget_get_mapped (widget)))
+                return;
+
+        if (terminal->pvt->visible_bell_tag != 0) {
+                g_source_remove (terminal->pvt->visible_bell_tag);
+        } else {
 		/* Force the repaint, max delay of UPDATE_REPEAT_TIMEOUT */
 		_vte_invalidate_all (terminal);
 	}
+        terminal->pvt->visible_bell_tag = g_timeout_add_full (G_PRIORITY_LOW,
+                                                              VTE_VISIBLE_BELL_DURATION,
+                                                              (GSourceFunc)stop_visible_beep,
+                                                              terminal,
+                                                              NULL);
 }
 
 void
@@ -8050,6 +8085,7 @@ vte_terminal_init(VteTerminal *terminal)
 	pvt->pending = g_array_new(FALSE, TRUE, sizeof(gunichar));
 	pvt->max_input_bytes = VTE_MAX_INPUT_READ;
 	pvt->cursor_blink_tag = 0;
+	pvt->visible_bell_tag = 0;
 	pvt->outgoing = _vte_byte_array_new();
 	pvt->outgoing_conv = VTE_INVALID_CONV;
 	pvt->conv_buffer = _vte_byte_array_new();
@@ -8322,6 +8358,7 @@ vte_terminal_unrealize(GtkWidget *widget)
 
 	/* Remove the blink timeout function. */
 	remove_cursor_timeout(terminal);
+        remove_visible_bell_timeout(terminal);
 
 	/* Cancel any pending redraws. */
 	remove_update_timeout (terminal);
@@ -8536,6 +8573,8 @@ vte_terminal_finalize(GObject *object)
 		_vte_matcher_free(terminal->pvt->matcher);
 	}
 
+        remove_cursor_timeout (terminal);
+        remove_visible_bell_timeout (terminal);
 	remove_update_timeout (terminal);
 
 	/* discard title updates */
@@ -8717,7 +8756,7 @@ vte_terminal_determine_colors_internal(VteTerminal *terminal,
 	}
 
 	/* Reverse cell? */
-	if (cell->attr.reverse) {
+        if (cell->attr.reverse != !!terminal->pvt->visible_bell_tag) {
 		swap (&fore, &back);
 	}
 
