patch 9.1.1211: TabClosedPre is triggered just before the tab is being freed

Problem:  TabClosedPre is triggered just before the tab is being freed,
          which limited its functionality.
Solution: Trigger it a bit earlier and also on :tabclose and :tabonly
          (Jim Zhou)

closes: #16890

Signed-off-by: Jim Zhou <jimzhouzzy@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/window.c b/src/window.c
index cce7f4c..55168d5 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2978,10 +2978,15 @@
     recursive = FALSE;
 }
 
-    static void
-trigger_tabclosedpre(tabpage_T *tp)
+/*
+ * directly is TRUE if the window is closed by ':tabclose' or ':tabonly'.
+ * This allows saving the session before closing multi-window tab.
+ */
+    void
+trigger_tabclosedpre(tabpage_T *tp, int directly)
 {
     static int	recursive = FALSE;
+    static int	skip = FALSE;
     tabpage_T	*ptp = curtab;
 
     // Quickly return when no TabClosedPre autocommands to be executed or
@@ -2989,8 +2994,19 @@
     if (!has_tabclosedpre() || recursive)
 	return;
 
+    // Skip if the event have been triggered by ':tabclose' recently
+    if (skip)
+    {
+	skip = FALSE;
+	return;
+    }
+
     if (valid_tabpage(tp))
+    {
 	goto_tabpage_tp(tp, FALSE, FALSE);
+	if (directly)
+	    skip = TRUE;
+    }
     recursive = TRUE;
     window_layout_lock();
     apply_autocmds(EVENT_TABCLOSEDPRE, NULL, NULL, FALSE, NULL);
@@ -3382,7 +3398,7 @@
 
     if (tp->tp_firstwin == tp->tp_lastwin)
     {
-	trigger_tabclosedpre(tp);
+	trigger_tabclosedpre(tp, FALSE);
 	// autocmd may have freed the window already.
 	if (!win_valid_any_tab(win))
 	    return;