diff --git a/src/vte.cc b/src/vte.cc
index ed8977c1..27689544 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -433,10 +433,6 @@ VteTerminalPrivate::invalidate_all()
 	_vte_debug_print (VTE_DEBUG_WORK, "*");
 	_vte_debug_print (VTE_DEBUG_UPDATES, "Invalidating all.\n");
 
-        /* this sometimes saves us a full repaint after blinking has stopped,
-         * otherwise not important to have here */
-        remove_text_blink_timeout();
-
 	/* replace invalid regions with one covering the whole terminal */
 	reset_update_rects();
 	m_invalidated_all = TRUE;
@@ -8539,8 +8535,13 @@ VteTerminalPrivate::widget_settings_notify()
 
         /* Misuse gtk-cursor-blink-time for text blinking as well. This might change in the future. */
         m_text_blink_cycle = m_cursor_blink_cycle;
-        if (m_text_blink_tag != 0)
+        if (m_text_blink_tag != 0) {
+                /* The current phase might have changed, and an already installed
+                 * timer to blink might fire too late. So remove the timer and
+                 * repaint the contents (which will install a correct new timer). */
+                remove_text_blink_timeout();
                 invalidate_all();
+        }
 }
 
 void
@@ -8963,7 +8964,7 @@ VteTerminalPrivate::determine_cursor_colors(VteCell const* cell,
 }
 
 static gboolean
-invalidate_blink_cb(VteTerminalPrivate *that)
+invalidate_text_blink_cb(VteTerminalPrivate *that)
 {
         that->m_text_blink_tag = 0;
         that->invalidate_all();
@@ -10145,12 +10146,16 @@ VteTerminalPrivate::widget_draw(cairo_t *cr)
 
         cairo_region_destroy (region);
 
-        /* If painting encountered any cell with blink attribute,
-         * we might need to set up a timer. */
+        /* If painting encountered any cell with blink attribute, we might need to set up a timer.
+         * Blinking is implemented using a one-shot (not repeating) timer that keeps getting reinstalled
+         * here as long as blinking cells are encountered during (re)painting. This way there's no need
+         * for an explicit step to stop the timer when blinking cells are no longer present, this happens
+         * implicitly by the timer not getting reinstalled anymore (often after a final unnecessary but
+         * harmless repaint). */
         if (G_UNLIKELY (m_text_to_blink && text_blink_enabled_now && m_text_blink_tag == 0))
                 m_text_blink_tag = g_timeout_add_full(G_PRIORITY_LOW,
                                                       m_text_blink_cycle - now % m_text_blink_cycle,
-                                                      (GSourceFunc)invalidate_blink_cb,
+                                                      (GSourceFunc)invalidate_text_blink_cb,
                                                       this,
                                                       NULL);
 
