diff --git a/src/vte.cc b/src/vte.cc
index 0c8f741a..4a0503d2 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -2273,7 +2273,11 @@ VteTerminalPrivate::update_insert_delta()
 void
 VteTerminalPrivate::apply_mouse_cursor()
 {
-        /* See bug 789390 for the m_mouse_cursor_over_widget condition. */
+        /* Show the cursor if over the widget and not autohidden, this is obvious.
+         * Also show the cursor if outside the widget regardless of the autohidden state, so that if a popover is opened
+         * and then the cursor returns (which doesn't trigger an enter_notify_event), it is visible.
+         * That is, only hide the cursor if it's over the widget and is autohidden.
+         * See bug 789390 and bug 789536 comment 6 for details. */
         m_mouse_cursor_visible = !(m_mouse_autohide && m_mouse_cursor_autohidden && m_mouse_cursor_over_widget);
 
         if (!widget_realized())
@@ -2310,8 +2314,21 @@ VteTerminalPrivate::apply_mouse_cursor()
 void
 VteTerminalPrivate::set_pointer_autohidden(bool autohidden)
 {
+        if (autohidden == m_mouse_cursor_autohidden)
+                return;
+
         m_mouse_cursor_autohidden = autohidden;
-        apply_mouse_cursor();
+
+        if (m_mouse_autohide) {
+                /* The order of these two steps is important: the mouse cursor can depend on the regex/hyperlink match. */
+                // FIXME update regex highlight here
+                if (m_mouse_cursor_over_widget) {
+                        hyperlink_hilite_update(m_mouse_last_position);
+                        match_hilite_update(m_mouse_last_position);
+                }
+
+                apply_mouse_cursor();
+        }
 }
 
 /*
@@ -5604,9 +5621,9 @@ VteTerminalPrivate::hyperlink_hilite_update(vte::view::coords const& pos)
         _vte_debug_print (VTE_DEBUG_HYPERLINK,
                          "hyperlink_hilite_update\n");
 
-        coords_visible = view_coords_visible(pos);
+        coords_visible = view_coords_visible(pos) && m_mouse_cursor_over_widget && !(m_mouse_autohide && m_mouse_cursor_autohidden);
         if (coords_visible) {
-                rowcol = grid_coords_from_view_coords(pos);
+                rowcol = confined_grid_coords_from_view_coords(pos);
                 rowdata = find_row_data(rowcol.row());
                 if (rowdata && rowcol.column() < rowdata->len) {
                         new_hyperlink_hover_idx = rowdata->cells[rowcol.column()].attr.hyperlink_idx;
@@ -5658,29 +5675,6 @@ VteTerminalPrivate::hyperlink_hilite_update(vte::view::coords const& pos)
         emit_hyperlink_hover_uri_changed(m_hyperlink_hover_idx != 0 ? &bbox : NULL);
 }
 
-/*
- * VteTerminalPrivate::hyperlink_hilite:
- *
- * If the mouse moved to a new cell, updates the hyperlinks via hyperlink_hilite_update().
- */
-void
-VteTerminalPrivate::hyperlink_hilite(vte::view::coords const& pos)
-{
-        /* if the cursor is not above a cell, skip */
-        if (!view_coords_visible(pos))
-                return;
-
-        /* If the pointer hasn't moved to another character cell, then we
-         * need do nothing. Note: Don't use mouse_last_row as that's relative
-         * to insert_delta, and we care about the absolute row number. */
-        if (grid_coords_from_view_coords(pos) ==
-             confined_grid_coords_from_view_coords(m_mouse_last_position)) {
-                return;
-        }
-
-       hyperlink_hilite_update(pos);
-}
-
 /*
  * VteTerminalPrivate::match_hilite_clear:
  *
@@ -7146,7 +7140,7 @@ VteTerminalPrivate::widget_motion_notify(GdkEventMotion *event)
 		match_hilite_hide();
 	} else if (pos != m_mouse_last_position) {
 		/* Hilite any matches. */
-                hyperlink_hilite(pos);
+                hyperlink_hilite_update(pos);
 		match_hilite(pos);
 		/* Show the cursor. */
                 set_pointer_autohidden(false);
@@ -7207,7 +7201,7 @@ VteTerminalPrivate::widget_button_press(GdkEventButton *event)
         auto pos = view_coords_from_event(base_event);
         auto rowcol = grid_coords_from_view_coords(pos);
 
-        hyperlink_hilite(pos);
+        hyperlink_hilite_update(pos);
 	match_hilite(pos);
 
         set_pointer_autohidden(false);
@@ -7358,7 +7352,7 @@ VteTerminalPrivate::widget_button_release(GdkEventButton *event)
         auto pos = view_coords_from_event(base_event);
         auto rowcol = grid_coords_from_view_coords(pos);
 
-        hyperlink_hilite(pos);
+        hyperlink_hilite_update(pos);
 	match_hilite(pos);
 
         set_pointer_autohidden(false);
@@ -7480,6 +7474,8 @@ VteTerminalPrivate::widget_enter(GdkEventCrossing *event)
         match_hilite_show(pos);
 
         m_mouse_cursor_over_widget = TRUE;
+        hyperlink_hilite_update(pos);
+        set_pointer_autohidden (FALSE);  // required??
         apply_mouse_cursor();
 
         m_mouse_last_position = pos;
@@ -7500,6 +7496,7 @@ VteTerminalPrivate::widget_leave(GdkEventCrossing *event)
          * buffer after each update for nothing...)
          */
         m_mouse_cursor_over_widget = FALSE;
+        hyperlink_hilite_update(pos);
         apply_mouse_cursor();
 
         m_mouse_last_position = pos;
@@ -10608,7 +10605,17 @@ VteTerminalPrivate::set_mouse_autohide(bool autohide)
                 return false;
 
 	m_mouse_autohide = autohide;
-        apply_mouse_cursor();
+
+        if (m_mouse_cursor_autohidden) {
+                /* The order of these two steps is important: the mouse cursor can depend on the regex/hyperlink match. */
+                // FIXME update regex matches here
+                if (m_mouse_cursor_over_widget) {
+                        hyperlink_hilite_update(m_mouse_last_position);
+                        match_hilite_update(m_mouse_last_position);
+                }
+
+                apply_mouse_cursor();
+        }
         return true;
 }
 
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index fe63e76c..dd8627c4 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -540,10 +540,9 @@ public:
         guint m_mouse_handled_buttons;      /* similar bitmap for buttons we handled ourselves */
         /* The last known position the mouse pointer from an event. We don't store
          * this in grid coordinates because we want also to check if they were outside
-         * the viewable area.
+         * the viewable area, and also want to catch in-cell movements if they make the pointer visible.
          */
         vte::view::coords m_mouse_last_position;
-        gboolean m_mouse_autohide;
         guint m_mouse_autoscroll_tag;
         gboolean m_mouse_xterm_extension;
         gboolean m_mouse_urxvt_extension;
@@ -612,8 +611,9 @@ public:
         VtePaletteColor m_palette[VTE_PALETTE_SIZE];
 
 	/* Mouse cursors. */
-        gboolean m_mouse_cursor_over_widget;
-        gboolean m_mouse_cursor_autohidden;  /* whether the autohiding logic wants to hide it; even if autohiding is disabled */
+        gboolean m_mouse_cursor_over_widget; /* as per enter and leave events */
+        gboolean m_mouse_autohide;           /* the API setting */
+        gboolean m_mouse_cursor_autohidden;  /* whether the autohiding logic wants to hide it; even if autohiding is disabled via API */
         gboolean m_mouse_cursor_visible;     /* derived value really containing if it's actually visible */
         GdkCursor* m_mouse_default_cursor;
         GdkCursor* m_mouse_mousing_cursor;
