implement firefox like behaviour for selecting tabs after closing current tab
This commit is contained in:
parent
b417f2a23b
commit
1a7d4b476b
|
|
@ -208,6 +208,10 @@ class CommandDispatcher:
|
|||
raise cmdutils.CommandError(
|
||||
"-o is not supported with 'tabs.select_on_remove' set to "
|
||||
"'last-used'!")
|
||||
elif conf_selection == 'firefox':
|
||||
raise cmdutils.CommandError(
|
||||
"-o is not supported with 'tabs.select_on_remove' set to "
|
||||
"'firefox'!")
|
||||
else: # pragma: no cover
|
||||
raise ValueError("Invalid select_on_remove value "
|
||||
"{!r}!".format(conf_selection))
|
||||
|
|
@ -233,7 +237,7 @@ class CommandDispatcher:
|
|||
else:
|
||||
old_selection_behavior = tabbar.selectionBehaviorOnRemove()
|
||||
tabbar.setSelectionBehaviorOnRemove(selection_override)
|
||||
self._tabbed_browser.close_tab(tab)
|
||||
self._tabbed_browser.close_tab(tab, allow_firefox_behavior=False)
|
||||
tabbar.setSelectionBehaviorOnRemove(old_selection_behavior)
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||
|
|
|
|||
|
|
@ -1890,6 +1890,11 @@ class SelectOnRemove(MappingType):
|
|||
QTabBar.SelectionBehavior.SelectPreviousTab,
|
||||
"Select the previously selected tab.",
|
||||
),
|
||||
'firefox': (
|
||||
'firefox',
|
||||
("Select the tab that was opened before this tab (if closed immediately "
|
||||
"without switching away). Falls back to 'next' otherwise."),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from typing import (
|
|||
Any, Optional)
|
||||
from collections.abc import Mapping, MutableMapping, MutableSequence
|
||||
|
||||
from qutebrowser.qt.widgets import QSizePolicy, QWidget, QApplication
|
||||
from qutebrowser.qt.widgets import QSizePolicy, QWidget, QApplication, QTabBar
|
||||
from qutebrowser.qt.core import pyqtSignal, pyqtSlot, QTimer, QUrl, QPoint
|
||||
|
||||
from qutebrowser.config import config
|
||||
|
|
@ -242,6 +242,8 @@ class TabbedBrowser(QWidget):
|
|||
self.default_window_icon = self._window().windowIcon()
|
||||
self.is_private = private
|
||||
self.tab_deque = TabDeque()
|
||||
# Last opened tab tracking for tabs.select_on_remove = 'firefox'
|
||||
self._opened_tab: Optional[weakref.ReferenceType[browsertab.AbstractTab]] = None
|
||||
config.instance.changed.connect(self._on_config_changed)
|
||||
quitter.instance.shutting_down.connect(self.shutdown)
|
||||
|
||||
|
|
@ -444,7 +446,30 @@ class TabbedBrowser(QWidget):
|
|||
else:
|
||||
yes_action()
|
||||
|
||||
def close_tab(self, tab, *, add_undo=True, new_undo=True, transfer=False):
|
||||
def _should_select_opener(self, tab):
|
||||
"""Check if we should select the opener tab (behave like last-used).
|
||||
|
||||
Args:
|
||||
tab: The tab that is about to be closed.
|
||||
|
||||
Return:
|
||||
True if we should fall back to 'last-used' behavior to select the opener.
|
||||
False if we should stick to the default (next).
|
||||
"""
|
||||
# Only apply if config is 'firefox' mode
|
||||
if config.val.tabs.select_on_remove != 'firefox':
|
||||
return False
|
||||
|
||||
if self._opened_tab is None:
|
||||
return False
|
||||
|
||||
opened = self._opened_tab()
|
||||
self._opened_tab = None # Clear state
|
||||
|
||||
return opened is tab
|
||||
|
||||
def close_tab(self, tab, *, add_undo=True, new_undo=True, transfer=False,
|
||||
allow_firefox_behavior=True):
|
||||
"""Close a tab.
|
||||
|
||||
Args:
|
||||
|
|
@ -452,6 +477,7 @@ class TabbedBrowser(QWidget):
|
|||
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.
|
||||
allow_firefox_behavior: Whether to try selecting the 'opener' tab (if configured).
|
||||
"""
|
||||
if config.val.tabs.tabs_are_windows or transfer:
|
||||
last_close = 'close'
|
||||
|
|
@ -463,8 +489,20 @@ class TabbedBrowser(QWidget):
|
|||
if last_close == 'ignore' and count == 1:
|
||||
return
|
||||
|
||||
# Handle 'firefox' selection mode
|
||||
restore_behavior = None
|
||||
if allow_firefox_behavior and self._should_select_opener(tab):
|
||||
# Temporarily switch to 'last-used' behavior, which will select the 'opener'
|
||||
# since we verified the relationship and navigation state.
|
||||
tabbar = self.widget.tabBar()
|
||||
restore_behavior = tabbar.selectionBehaviorOnRemove()
|
||||
tabbar.setSelectionBehaviorOnRemove(QTabBar.SelectionBehavior.SelectPreviousTab)
|
||||
|
||||
self._remove_tab(tab, add_undo=add_undo, new_undo=new_undo)
|
||||
|
||||
if restore_behavior is not None:
|
||||
self.widget.tabBar().setSelectionBehaviorOnRemove(restore_behavior)
|
||||
|
||||
if count == 1: # We just closed the last tab above.
|
||||
if last_close == 'close':
|
||||
self.close_window.emit()
|
||||
|
|
@ -659,6 +697,11 @@ class TabbedBrowser(QWidget):
|
|||
|
||||
if background is None:
|
||||
background = config.val.tabs.background
|
||||
|
||||
# Track opened tab for tabs.select_on_remove = 'firefox'
|
||||
if self.widget.count() > 0:
|
||||
self._opened_tab = weakref.ref(tab)
|
||||
|
||||
if background:
|
||||
# Make sure the background tab has the correct initial size.
|
||||
# With a foreground tab, it's going to be resized correctly by the
|
||||
|
|
@ -904,6 +947,13 @@ class TabbedBrowser(QWidget):
|
|||
.format(idx))
|
||||
return
|
||||
|
||||
# Clear state if user switched to a tab that's not the opened tab
|
||||
if self._opened_tab is not None:
|
||||
opened = self._opened_tab()
|
||||
if tab is not opened:
|
||||
# User navigated to a third tab, forget opened tab
|
||||
self._opened_tab = None
|
||||
|
||||
log.modes.debug("Current tab changed, focusing {!r}".format(tab))
|
||||
tab.setFocus()
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,12 @@ class TabWidget(QTabWidget):
|
|||
tabbar = self.tab_bar()
|
||||
tabbar.vertical = position in [
|
||||
QTabWidget.TabPosition.West, QTabWidget.TabPosition.East]
|
||||
tabbar.setSelectionBehaviorOnRemove(selection_behavior)
|
||||
# 'firefox' mode uses custom selection logic; fall back to 'next' for Qt
|
||||
if selection_behavior == 'firefox':
|
||||
tabbar.setSelectionBehaviorOnRemove(
|
||||
QTabBar.SelectionBehavior.SelectRightTab)
|
||||
else:
|
||||
tabbar.setSelectionBehaviorOnRemove(selection_behavior)
|
||||
tabbar.refresh()
|
||||
|
||||
def tab_bar(self) -> "TabBar":
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
Feature: Tab selection on remove (firefox behavior)
|
||||
Tests for tabs.select_on_remove = firefox
|
||||
|
||||
Background:
|
||||
Given I clean up open tabs
|
||||
And I set tabs.tabs_are_windows to false
|
||||
And I set tabs.background to false
|
||||
And I clear the log
|
||||
|
||||
Scenario: :tab-close with tabs.select_on_remove = firefox
|
||||
When I set tabs.select_on_remove to firefox
|
||||
And I open data/numbers/1.txt
|
||||
And I open data/numbers/2.txt in a new tab
|
||||
And I open data/numbers/3.txt in a new tab
|
||||
And I open data/numbers/4.txt in a new tab
|
||||
And I run :tab-focus 2
|
||||
And I run :tab-close
|
||||
Then the following tabs should be open:
|
||||
"""
|
||||
- data/numbers/1.txt
|
||||
- data/numbers/3.txt (active)
|
||||
- data/numbers/4.txt
|
||||
"""
|
||||
|
||||
Scenario: :tab-close with tabs.select_on_remove = firefox
|
||||
When I set tabs.select_on_remove to firefox
|
||||
And I open data/numbers/1.txt
|
||||
And I open data/numbers/2.txt in a new tab
|
||||
And I open data/numbers/3.txt in a new tab
|
||||
And I run :tab-focus 1
|
||||
And I open data/numbers/4.txt in a new tab
|
||||
And I run :tab-close
|
||||
Then the following tabs should be open:
|
||||
"""
|
||||
- data/numbers/1.txt (active)
|
||||
- data/numbers/2.txt
|
||||
- data/numbers/3.txt
|
||||
"""
|
||||
|
||||
Scenario: Error with --opposite
|
||||
When I set tabs.select_on_remove to firefox
|
||||
And I run :tab-close --opposite
|
||||
Then the error "-o is not supported with 'tabs.select_on_remove' set to 'firefox'!" should be shown
|
||||
|
||||
Scenario: Override with --next
|
||||
When I set tabs.select_on_remove to firefox
|
||||
And I open data/numbers/1.txt
|
||||
And I open data/numbers/2.txt in a new tab
|
||||
And I open data/numbers/3.txt in a new tab
|
||||
And I open data/numbers/4.txt in a new tab
|
||||
And I run :tab-focus 2
|
||||
And I run :tab-close --next
|
||||
Then the following tabs should be open:
|
||||
"""
|
||||
- data/numbers/1.txt
|
||||
- data/numbers/3.txt (active)
|
||||
- data/numbers/4.txt
|
||||
"""
|
||||
|
||||
Scenario: Override with --prev
|
||||
When I set tabs.select_on_remove to firefox
|
||||
And I open data/numbers/1.txt
|
||||
And I open data/numbers/2.txt in a new tab
|
||||
And I open data/numbers/3.txt in a new tab
|
||||
And I open data/numbers/4.txt in a new tab
|
||||
And I run :tab-focus 3
|
||||
And I run :tab-close --prev
|
||||
Then the following tabs should be open:
|
||||
"""
|
||||
- data/numbers/1.txt
|
||||
- data/numbers/2.txt (active)
|
||||
- data/numbers/4.txt
|
||||
"""
|
||||
|
||||
Scenario: :tab-close with tabs.select_on_remove = firefox and --opposite
|
||||
When I set tabs.select_on_remove to firefox
|
||||
And I run :tab-close --opposite
|
||||
Then the error "-o is not supported with 'tabs.select_on_remove' set to 'firefox'!" should be shown
|
||||
Loading…
Reference in New Issue