Repository: qutebrowser/qutebrowser

Issue:
Taking a tab doesn't close the tab if it's the only tab in a window
**Version info**:
qutebrowser v1.11.1
Backend: QtWebEngine (Chromium 73.0.3683.105)
Qt: 5.13.2

**Does the bug happen if you start with `--temp-basedir`?**:
Yes.

**Description**
If you take a tab to window A from window B using `tab-take`, it's opened in window A and the instance in window B closes, likely through `tab-close`. (This, I presume, is the expected behavior.) However, if the tab is the only tab in window B, `tab-take` doesn't close the tab, so there's a copy in both window A and window B.

**How to reproduce**
1. Open two windows of qutebrowser.
2. From the first window, run: `tab-take 1/0`



Discussion:
This is consistent with what happens when you try to close the last tab in a window normally (i.e. via `d`). If you prefer the window to be closed in such cases, you can set `tabs.last_close` to `close`.

However, since this isn't the first time this is coming up (#4979, cc @jhultman), I'm okay with forcing the window to close (no matter what `tabs.last_close` is) in that case.
I didn't know about that option, it seems to solve the problem. Thanks for the quick reply!
This is also an issue with tab-give, though in that case it's less inconvenient to close it as a separate step.

I have tabs.last_close set to ignore because I found that it made it easier to recover from accidentally closing tabs. This usually happened due to thinking I was in insert mode, and then typing something with a 'd' in it.

tab-give and tab-take don't have default key-bindings (and I wouldn't expect anyone add a single-key binding), so I think the main reasons for using the tabs.last_close setting don't apply here. So I'd support either always closing in this situation, or having a "tabs.last_give" setting to determine behaviour in this case. However, I don't think it's a particular important issue.
@andrewcarlotti FWIW with `:undo --window` (`Shift-U`) being a thing now, this would only apply if you accidentally close the last tab in the last window (causing qutebrowser to quit).

Resolving patch:
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -451,7 +451,7 @@ def tab_take(self, index, keep=False):
 
         self._open(tab.url(), tab=True)
         if not keep:
-            tabbed_browser.close_tab(tab, add_undo=False)
+            tabbed_browser.close_tab(tab, add_undo=False, transfer=True)
 
     @cmdutils.register(instance='command-dispatcher', scope='window')
     @cmdutils.argument('win_id', completion=miscmodels.window)
@@ -500,7 +500,8 @@ def tab_give(self, win_id: int = None, keep: bool = False,
         tabbed_browser.tabopen(self._current_url())
         if not keep:
             self._tabbed_browser.close_tab(self._current_widget(),
-                                           add_undo=False)
+                                           add_undo=False,
+                                           transfer=True)
 
     def _back_forward(self, tab, bg, window, count, forward, index=None):
         """Helper function for :back/:forward."""
diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py
--- a/qutebrowser/mainwindow/tabbedbrowser.py
+++ b/qutebrowser/mainwindow/tabbedbrowser.py
@@ -406,15 +406,16 @@ def tab_close_prompt_if_pinned(
         else:
             yes_action()
 
-    def close_tab(self, tab, *, add_undo=True, new_undo=True):
+    def close_tab(self, tab, *, add_undo=True, new_undo=True, transfer=False):
         """Close a tab.
 
         Args:
             tab: The QWebView to be closed.
             add_undo: Whether the tab close can be undone.
             new_undo: Whether the undo entry should be a new item in the stack.
+            transfer: Whether the tab is closing because it is moving to a new window.
         """
-        if config.val.tabs.tabs_are_windows:
+        if config.val.tabs.tabs_are_windows or transfer:
             last_close = 'close'
         else:
             last_close = config.val.tabs.last_close


Test patch:
diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature
--- a/tests/end2end/features/tabs.feature
+++ b/tests/end2end/features/tabs.feature
@@ -1349,6 +1349,25 @@ Feature: Tab management
         And I run :tab-take 0/1
         Then the error "Can't take tabs when using windows as tabs" should be shown
 
+    @windows_skip
+    Scenario: Close the last tab of a window when taken by another window
+        Given I have a fresh instance
+        When I open data/numbers/1.txt
+        And I run :tab-only
+        And I open data/numbers/2.txt in a new window
+        And I set tabs.last_close to ignore
+        And I run :tab-take 1/1
+        And I wait until data/numbers/2.txt is loaded
+        Then the session should look like:
+            windows:
+            - tabs:
+              - history:
+                - url: about:blank
+                - url: http://localhost:*/data/numbers/1.txt
+              - active: true
+                history:
+                - url: http://localhost:*/data/numbers/2.txt
+
     # :tab-give
 
     @xfail_norun  # Needs qutewm
@@ -1406,6 +1425,24 @@ Feature: Tab management
         And I run :tab-give 0
         Then the error "Can't give tabs when using windows as tabs" should be shown
 
+    @windows_skip
+    Scenario: Close the last tab of a window when given to another window
+        Given I have a fresh instance
+        When I open data/numbers/1.txt
+        And I run :tab-only
+        And I open data/numbers/2.txt in a new window
+        And I set tabs.last_close to ignore
+        And I run :tab-give 1
+        And I wait until data/numbers/1.txt is loaded
+        Then the session should look like:
+            windows:
+            - tabs:
+              - active: true
+                history:
+                - url: http://localhost:*/data/numbers/2.txt
+              - history:
+                - url: http://localhost:*/data/numbers/1.txt
+
     # Other
 
     Scenario: Using :tab-next after closing last tab (#1448)