diff --git a/qutebrowser/app.py b/qutebrowser/app.py index bcae86dd7..2c8fb72a6 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -214,13 +214,15 @@ def _process_args(args): if not sessions.session_manager.did_load: log.init.debug("Initializing main window...") - if config.val.content.private_browsing and qtutils.is_single_process(): + private = args.target == 'private-window' + if (config.val.content.private_browsing or + private) and qtutils.is_single_process(): err = Exception("Private windows are unavailable with " "the single-process process model.") error.handle_fatal_exc(err, 'Cannot start in private mode', no_err_windows=args.no_err_windows) sys.exit(usertypes.Exit.err_init) - window = mainwindow.MainWindow(private=None) + window = mainwindow.MainWindow(private=private) if not args.nowindow: window.show() q_app.setActiveWindow(window) @@ -246,8 +248,10 @@ def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None): ipc. If the --target argument was not specified, target_arg will be an empty string. """ + is_private = 'private-window' if target_arg == 'private-window' else None if via_ipc and not args: - win_id = mainwindow.get_window(via_ipc, force_window=True) + win_id = mainwindow.get_window(via_ipc, force_window=True, + force_target=is_private) _open_startpage(win_id) return win_id = None @@ -260,7 +264,8 @@ def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None): commandrunner.run_safely(cmd[1:]) elif not cmd: log.init.debug("Empty argument") - win_id = mainwindow.get_window(via_ipc, force_window=True) + win_id = mainwindow.get_window(via_ipc, force_window=True, + force_target=is_private) else: if via_ipc and target_arg and target_arg != 'auto': open_target = target_arg diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 2b5741586..568fab60a 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -72,6 +72,7 @@ new_instance_open_target: - tab-bg-silent: Open a new background tab in the existing window without activating the window. - window: Open in a new window. + - private-window: Open in a new private window. default: tab desc: >- How to open links in an existing instance if a new one is launched. diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 6e1505807..2f5db9ab4 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -26,7 +26,7 @@ import functools import typing from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QRect, QPoint, QTimer, Qt, - QCoreApplication, QEventLoop) + QCoreApplication, QEventLoop, QByteArray, QObject) from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QSizePolicy from PyQt5.QtGui import QPalette @@ -46,8 +46,11 @@ from qutebrowser.qt import sip win_id_gen = itertools.count(0) -def get_window(via_ipc, force_window=False, force_tab=False, - force_target=None, no_raise=False): +def get_window(via_ipc: bool, + force_window: bool = False, + force_tab: bool = False, + force_target: typing.Optional[bool] = None, + no_raise: bool = False): """Helper function for app.py to get a window id. Args: @@ -72,9 +75,9 @@ def get_window(via_ipc, force_window=False, force_tab=False, # Apply any target overrides, ordered by precedence if force_target is not None: open_target = force_target - if force_window: + if force_window and open_target != 'private-window': open_target = 'window' - if force_tab and open_target == 'window': + if force_tab and open_target in {'window', 'private-window'}: # Command sent via IPC open_target = 'tab-silent' @@ -82,13 +85,15 @@ def get_window(via_ipc, force_window=False, force_tab=False, should_raise = False # Try to find the existing tab target if opening in a tab - if open_target != 'window': + if open_target not in {'window', 'private-window'}: window = get_target_window() - should_raise = open_target not in ['tab-silent', 'tab-bg-silent'] + should_raise = open_target not in {'tab-silent', 'tab-bg-silent'} + + is_private = open_target == 'private-window' # Otherwise, or if no window was found, create a new one if window is None: - window = MainWindow(private=None) + window = MainWindow(private=is_private) window.show() should_raise = True @@ -137,7 +142,6 @@ _OverlayInfoType = typing.Tuple[QWidget, pyqtSignal, bool, str] class MainWindow(QWidget): - """The main window of qutebrowser. Adds all needed components to a vbox, initializes sub-widgets and connects @@ -200,7 +204,10 @@ class MainWindow(QWidget): } """ - def __init__(self, *, private, geometry=None, parent=None): + def __init__(self, *, + private: bool, + geometry: typing.Optional[QByteArray] = None, + parent: typing.Optional[QObject] = None) -> None: """Create a new main window. Args: @@ -217,6 +224,7 @@ class MainWindow(QWidget): self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_TranslucentBackground) self.palette().setColor(QPalette.Window, Qt.transparent) + self._commandrunner = None self._overlays = [] # type: typing.MutableSequence[_OverlayInfoType] self.win_id = next(win_id_gen) self.registry = objreg.ObjectRegistry() diff --git a/qutebrowser/qutebrowser.py b/qutebrowser/qutebrowser.py index bbe56c6c7..93c38d841 100644 --- a/qutebrowser/qutebrowser.py +++ b/qutebrowser/qutebrowser.py @@ -77,7 +77,7 @@ def get_argparser(): action='store_true') parser.add_argument('--target', choices=['auto', 'tab', 'tab-bg', 'tab-silent', 'tab-bg-silent', - 'window'], + 'window', 'private-window'], help="How URLs should be opened if there is already a " "qutebrowser instance running.") parser.add_argument('--backend', choices=['webkit', 'webengine'], diff --git a/tests/end2end/features/invoke.feature b/tests/end2end/features/invoke.feature index 9be38659e..ee45dcb29 100644 --- a/tests/end2end/features/invoke.feature +++ b/tests/end2end/features/invoke.feature @@ -36,6 +36,21 @@ Feature: Invoking a new process - history: - url: http://localhost:*/data/search.html + Scenario: Using new_instance_open_target = private-window + When I set new_instance_open_target to private-window + And I open data/title.html + And I open data/search.html as a URL + Then the session should look like: + windows: + - tabs: + - history: + - url: about:blank + - url: http://localhost:*/data/title.html + - private: True + tabs: + - history: + - url: http://localhost:*/data/search.html + Scenario: Using new_instance_open_target_window = last-opened When I set new_instance_open_target to tab And I set new_instance_open_target_window to last-opened