(let ((frame (window-frame window)))
(cond
+ ((and tab-bar-mode
+ ;; Fall back to frame handling in case of less than 2 tabs
+ (> (length (funcall tab-bar-tabs-function frame)) 1)
+ ;; Close the tab with the initial window (bug#59862)
+ (or (eq (nth 1 (window-parameter window 'quit-restore)) 'tab)
+ ;; or with the dedicated window (bug#71386)
+ (and (window-dedicated-p window)
+ (frame-root-window-p window)))
+ ;; Don't close the tab if more windows were created explicitly
+ (< (seq-count (lambda (w)
+ (memq (car (window-parameter w 'quit-restore))
+ '(window tab frame same)))
+ (window-list-1 nil 'nomini))
+ 2))
+ 'tab)
((frame-root-window-p window)
;; WINDOW's frame can be deleted only if there are other frames
;; on the same terminal, and it does not contain the active
(unless (and dedicated-only (not (window-dedicated-p window)))
(let ((deletable (window-deletable-p window)))
(cond
+ ((eq deletable 'tab)
+ (tab-bar-close-tab)
+ (message "Tab closed after deleting the last window")
+ 'tab)
((eq deletable 'frame)
(let ((frame (window-frame window)))
(cond
;; If the previously selected window is still alive, select it.
(window--quit-restore-select-window quit-restore-2))
((and (not prev-buffer)
- (eq (nth 1 quit-restore) 'tab)
- (eq (nth 3 quit-restore) buffer))
- (tab-bar-close-tab)
- ;; If the previously selected window is still alive, select it.
- (window--quit-restore-select-window quit-restore-2))
- ((and (not prev-buffer)
- (or (eq (nth 1 quit-restore) 'frame)
+ (or (memq (nth 1 quit-restore) '(frame tab))
(and (eq (nth 1 quit-restore) 'window)
;; If the window has been created on an existing
;; frame and ended up as the sole window on that
(should (eq (length tab-bar-closed-tabs) 0)))
(ert-deftest tab-bar-tests-close-other-tabs-default ()
- (tab-bar-tests-close-other-tabs nil))
+ (tab-bar-tests-close-other-tabs nil)
+ ;; Clean up tabs afterwards
+ (tab-bar-tabs-set nil))
(ert-deftest tab-bar-tests-close-other-tabs-with-arg ()
- (dotimes (i 5) (tab-bar-tests-close-other-tabs i)))
+ (dotimes (i 5) (tab-bar-tests-close-other-tabs i))
+ ;; Clean up tabs afterwards
+ (tab-bar-tabs-set nil))
+
+(ert-deftest tab-bar-tests-quit-restore-window ()
+ (let* ((frame-params (when noninteractive
+ '((window-system . nil)
+ (tty-type . "linux"))))
+ (pop-up-frame-alist frame-params)
+ (frame-auto-hide-function 'delete-frame))
+
+ ;; 1.1. 'quit-restore-window' should delete the frame
+ ;; from initial window (bug#59862)
+ (progn
+ (should (eq (length (frame-list)) 1))
+ (other-frame-prefix)
+ (info)
+ (should (eq (length (frame-list)) 2))
+ (should (equal (buffer-name) "*info*"))
+ (view-echo-area-messages)
+ (other-window 1)
+ (should (eq (length (window-list)) 2))
+ (should (equal (buffer-name) "*Messages*"))
+ (quit-window)
+ (should (eq (length (window-list)) 1))
+ (should (equal (buffer-name) "*info*"))
+ (quit-window)
+ (should (eq (length (frame-list)) 1)))
+
+ ;; 1.2. 'quit-restore-window' should not delete the frame
+ ;; from non-initial window (bug#59862)
+ (progn
+ (should (eq (length (frame-list)) 1))
+ (other-frame-prefix)
+ (info)
+ (should (eq (length (frame-list)) 2))
+ (should (equal (buffer-name) "*info*"))
+ (view-echo-area-messages)
+ (should (eq (length (window-list)) 2))
+ (should (equal (buffer-name) "*info*"))
+ (quit-window)
+ (should (eq (length (window-list)) 1))
+ (should (eq (length (frame-list)) 2))
+ ;; FIXME: uncomment (should (equal (buffer-name) "*Messages*"))
+ (quit-window)
+ (should (eq (length (frame-list)) 2))
+ ;; Clean up the frame afterwards
+ (delete-frame))
+
+ ;; 2.1. 'quit-restore-window' should close the tab
+ ;; from initial window (bug#59862)
+ (progn
+ (should (eq (length (tab-bar-tabs)) 1))
+ (other-tab-prefix)
+ (info)
+ (should (eq (length (tab-bar-tabs)) 2))
+ (should (equal (buffer-name) "*info*"))
+ (view-echo-area-messages)
+ (other-window 1)
+ (should (eq (length (window-list)) 2))
+ (should (equal (buffer-name) "*Messages*"))
+ (quit-window)
+ (should (eq (length (window-list)) 1))
+ (should (equal (buffer-name) "*info*"))
+ (quit-window)
+ (should (eq (length (tab-bar-tabs)) 1)))
+
+ ;; 2.2. 'quit-restore-window' should not close the tab
+ ;; from non-initial window (bug#59862)
+ (progn
+ (should (eq (length (tab-bar-tabs)) 1))
+ (other-tab-prefix)
+ (info)
+ (should (eq (length (tab-bar-tabs)) 2))
+ (should (equal (buffer-name) "*info*"))
+ (view-echo-area-messages)
+ (should (eq (length (window-list)) 2))
+ (should (equal (buffer-name) "*info*"))
+ (quit-window)
+ (should (eq (length (window-list)) 1))
+ (should (eq (length (tab-bar-tabs)) 2))
+ (should (equal (buffer-name) "*Messages*"))
+ (quit-window)
+ (should (eq (length (tab-bar-tabs)) 2))
+ ;; Clean up the tab afterwards
+ (tab-close))
+
+ ;; 3. Don't delete the frame with dedicated window
+ ;; from the second tab (bug#71386)
+ (with-selected-frame (make-frame frame-params)
+ (switch-to-buffer (generate-new-buffer "test1"))
+ (tab-new)
+ (switch-to-buffer (generate-new-buffer "test2"))
+ (set-window-dedicated-p (selected-window) t)
+ (kill-buffer)
+ (should (eq (length (frame-list)) 2))
+ (should (eq (length (tab-bar-tabs)) 1))
+ ;; But now should delete the frame with dedicated window
+ ;; from the last tab
+ (set-window-dedicated-p (selected-window) t)
+ (kill-buffer)
+ (should (eq (length (frame-list)) 1)))
+
+ ;; Clean up tabs afterwards
+ (tab-bar-tabs-set nil)))
(provide 'tab-bar-tests)
;;; tab-bar-tests.el ends here