diff --git a/src/vte.cc b/src/vte.cc
index 609d4e2..8077c93 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -52,6 +52,7 @@
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
+#include <sys/time.h>
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <glib-object.h>
@@ -5983,7 +5984,7 @@ vte_terminal_cellattr_equal(VteCellAttr const *attr1,
  */
 char *
 VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
-                                     char const* text) const
+                                     char const* text)
 {
 	GString *string;
 	guint fore, back;
@@ -7803,6 +7804,7 @@ VteTerminalPrivate::VteTerminalPrivate(VteTerminal *t) :
 	m_pending = g_array_new(FALSE, TRUE, sizeof(gunichar));
 	m_max_input_bytes = VTE_MAX_INPUT_READ;
 	m_cursor_blink_tag = 0;
+	m_contents_blink_tag = 0;
 	m_outgoing = _vte_byte_array_new();
 	m_outgoing_conv = VTE_INVALID_CONV;
 	m_conv_buffer = _vte_byte_array_new();
@@ -8431,13 +8433,21 @@ swap (guint *a, guint *b)
 	tmp = *a, *a = *b, *b = tmp;
 }
 
+static gboolean
+invalidate_all_cb(VteTerminalPrivate *that)
+{
+        that->m_contents_blink_tag = 0;
+        that->invalidate_all();
+        return G_SOURCE_REMOVE;
+}
+
 // FIXMEchpe probably @attr should be passed by ref
 void
 VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
                                      bool is_selected,
                                      bool is_cursor,
                                      guint *pfore,
-                                     guint *pback) const
+                                     guint *pback)
 {
 	guint fore, back;
 
@@ -8508,9 +8518,20 @@ VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
                         swap (&fore, &back);
 	}
 
-	/* Invisible? */
+        /* Invisible? Blinking? */
 	if (attr->invisible) {
 		fore = back;
+        } else if (attr->blink) {
+                struct timeval tv;
+                gettimeofday(&tv, NULL);
+                if (tv.tv_sec % 2)
+                        fore = back;
+                if (m_contents_blink_tag == 0)
+                        m_contents_blink_tag = g_timeout_add_full(G_PRIORITY_LOW,
+                                                                  1000 - tv.tv_usec / 1000,
+                                                                  (GSourceFunc)invalidate_all_cb,
+                                                                  this,
+                                                                  NULL);
 	}
 
 	*pfore = fore;
@@ -8521,7 +8542,7 @@ void
 VteTerminalPrivate::determine_colors(VteCell const* cell,
                                      bool highlight,
                                      guint *fore,
-                                     guint *back) const
+                                     guint *back)
 {
 	determine_colors(cell ? &cell->attr : &basic_cell.cell.attr,
                          highlight, false /* not cursor */,
@@ -8532,7 +8553,7 @@ void
 VteTerminalPrivate::determine_cursor_colors(VteCell const* cell,
                                             bool highlight,
                                             guint *fore,
-                                            guint *back) const
+                                            guint *back)
 {
 	determine_colors(cell ? &cell->attr : &basic_cell.cell.attr,
                          highlight, true /* cursor */,
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index cff2157..9563003 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -406,6 +406,8 @@ public:
         gboolean m_cursor_visible;
         gboolean m_has_focus;               /* is the terminal window focused */
 
+        guint m_contents_blink_tag;
+
         /* DECSCUSR cursor style (shape and blinking possibly overridden
          * via escape sequence) */
         VteCursorStyle m_cursor_style;
@@ -834,18 +836,18 @@ public:
                                      bool selected,
                                      bool cursor,
                                      guint *pfore,
-                                     guint *pback) const;
+                                     guint *pback);
         inline void determine_colors(VteCell const* cell,
                                      bool selected,
                                      guint *pfore,
-                                     guint *pback) const;
+                                     guint *pback);
         inline void determine_cursor_colors(VteCell const* cell,
                                             bool selected,
                                             guint *pfore,
-                                            guint *pback) const;
+                                            guint *pback);
 
         char *cellattr_to_html(VteCellAttr const* attr,
-                               char const* text) const;
+                               char const* text);
         VteCellAttr const* char_to_cell_attr(VteCharAttributes const* attr) const;
 
         char *attributes_to_html(char const* text,
