Merge branch 'haasn-issue1060'

This commit is contained in:
Florian Bruhin 2016-08-17 12:05:01 +02:00
commit ea14b5bb42
10 changed files with 229 additions and 53 deletions

View File

@ -67,7 +67,7 @@ Changed
the most recently focused (instead of the last opened) window. This can be
configured with the new `new-instance-open-target.window` setting.
It can also be set to `last-visible` to show the pages in the most recently
visible window.
visible window, or `first-opened` to use the first (oldest) available window.
- Word hints now are more clever about getting the element text from some elements.
- Completions for `:help` and `:bind` now also show hidden commands
- The `:buffer` completion now also filters using the first column (id).
@ -79,6 +79,8 @@ Changed
- Counts can now be used with special keybindings (e.g. with modifiers).
This was already implemented for v0.7.0 originally, but got reverted because
it caused some issues and then never re-applied.
- Sending a command to an existing instance (via "qutebrowser :reload") now
doesn't mark it as urgent anymore.
Deprecated
~~~~~~~~~~

View File

@ -166,10 +166,10 @@ Contributors, sorted by the number of commits in descending order:
* Thorsten Wißmann
* Austin Anderson
* Jimmy
* Niklas Haas
* Alexey "Averrin" Nabrodov
* avk
* ZDarian
* Niklas Haas
* Milan Svoboda
* John ShaggyTwoDope Jenkins
* Peter Vilim

View File

@ -454,7 +454,8 @@ Which window to choose when opening links as new tabs.
Valid values:
* +last-opened+: Open new tabs in the last opened window.
* +first-opened+: Open new tabs in the first (oldest) opened window.
* +last-opened+: Open new tabs in the last (newest) opened window.
* +last-focused+: Open new tabs in the most recently focused window.
* +last-visible+: Open new tabs in the most recently visible window.

View File

@ -230,8 +230,10 @@ def data(readonly=False):
('new-instance-open-target.window',
SettingValue(typ.String(
valid_values=typ.ValidValues(
('last-opened', "Open new tabs in the last opened "
"window."),
('first-opened', "Open new tabs in the first (oldest) "
"opened window."),
('last-opened', "Open new tabs in the last (newest) "
"opened window."),
('last-focused', "Open new tabs in the most recently "
"focused window."),
('last-visible', "Open new tabs in the most recently "

View File

@ -54,44 +54,62 @@ def get_window(via_ipc, force_window=False, force_tab=False,
"""
if force_window and force_tab:
raise ValueError("force_window and force_tab are mutually exclusive!")
if not via_ipc:
# Initial main window
return 0
window_to_raise = None
open_target = config.get('general', 'new-instance-open-target')
# Apply any target overrides, ordered by precedence
if force_target is not None:
open_target = force_target
else:
open_target = config.get('general', 'new-instance-open-target')
if (open_target == 'window' or force_window) and not force_tab:
if force_window:
open_target = 'window'
if force_tab and open_target == 'window':
# Command sent via IPC
open_target = 'tab-silent'
window = None
raise_window = False
# Try to find the existing tab target if opening in a tab
if open_target != 'window':
window = get_target_window()
raise_window = open_target not in ['tab-silent', 'tab-bg-silent']
# Otherwise, or if no window was found, create a new one
if window is None:
window = MainWindow()
window.show()
win_id = window.win_id
window_to_raise = window
else:
raise_window = True
if raise_window:
window.setWindowState(window.windowState() & ~Qt.WindowMinimized)
window.setWindowState(window.windowState() | Qt.WindowActive)
window.raise_()
window.activateWindow()
QApplication.instance().alert(window)
return window.win_id
def get_target_window():
"""Get the target window for new tabs, or None if none exist."""
try:
win_mode = config.get('general', 'new-instance-open-target.window')
if win_mode == 'last-focused':
window = objreg.last_focused_window()
return objreg.last_focused_window()
elif win_mode == 'first-opened':
return objreg.window_by_index(0)
elif win_mode == 'last-opened':
window = objreg.last_window()
return objreg.window_by_index(-1)
elif win_mode == 'last-visible':
window = objreg.last_visible_window()
return objreg.last_visible_window()
else:
raise ValueError("Invalid win_mode {}".format(win_mode))
except objreg.NoWindow:
# There is no window left, so we open a new one
window = MainWindow()
window.show()
win_id = window.win_id
window_to_raise = window
win_id = window.win_id
if open_target not in ['tab-silent', 'tab-bg-silent']:
window_to_raise = window
if window_to_raise is not None:
window_to_raise.setWindowState(
window.windowState() & ~Qt.WindowMinimized | Qt.WindowActive)
window_to_raise.raise_()
window_to_raise.activateWindow()
QApplication.instance().alert(window_to_raise)
return win_id
return None
class MainWindow(QWidget):

View File

@ -298,13 +298,13 @@ def last_focused_window():
try:
return get('last-focused-main-window')
except KeyError:
return last_window()
return window_by_index(-1)
def last_window():
"""Get the last opened window object."""
def window_by_index(idx):
"""Get the Nth opened window object."""
if not window_registry:
raise NoWindow()
else:
key = sorted(window_registry)[-1]
key = sorted(window_registry)[idx]
return window_registry[key]

View File

@ -156,15 +156,18 @@ def open_path(quteproc, path):
"""Open a URL.
If used like "When I open ... in a new tab", the URL is opened in a new
tab. With "... in a new window", it's opened in a new window.
tab. With "... in a new window", it's opened in a new window. With
"... as a URL", it's opened according to new-instance-open-target.
"""
new_tab = False
new_window = False
as_url = False
wait = True
new_tab_suffix = ' in a new tab'
new_window_suffix = ' in a new window'
do_not_wait_suffix = ' without waiting'
as_url_suffix = ' as a URL'
if path.endswith(new_tab_suffix):
path = path[:-len(new_tab_suffix)]
@ -172,12 +175,16 @@ def open_path(quteproc, path):
elif path.endswith(new_window_suffix):
path = path[:-len(new_window_suffix)]
new_window = True
elif path.endswith(as_url_suffix):
path = path[:-len(as_url_suffix)]
as_url = True
if path.endswith(do_not_wait_suffix):
path = path[:-len(do_not_wait_suffix)]
wait = False
quteproc.open_path(path, new_tab=new_tab, new_window=new_window, wait=wait)
quteproc.open_path(path, new_tab=new_tab, new_window=new_window,
as_url=as_url, wait=wait)
@bdd.when(bdd.parsers.parse("I set {sect} -> {opt} to {value}"))

View File

@ -0,0 +1,108 @@
Feature: Invoking a new process
Simulate what happens when running qutebrowser with an existing instance
Background:
Given I clean up open tabs
Scenario: Using new-instance-open-target = tab
When I set general -> new-instance-open-target to tab
And I open data/title.html
And I open data/search.html as a URL
Then the following tabs should be open:
- data/title.html
- data/search.html (active)
Scenario: Using new-instance-open-target = tab-bg
When I set general -> new-instance-open-target to tab-bg
And I open data/title.html
And I open data/search.html as a URL
Then the following tabs should be open:
- data/title.html (active)
- data/search.html
Scenario: Using new-instance-open-target = window
When I set general -> new-instance-open-target to 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
- tabs:
- history:
- url: http://localhost:*/data/search.html
Scenario: Using new-instance-open-target.window = last-opened
When I set general -> new-instance-open-target to tab
And I set general -> new-instance-open-target.window to last-opened
And I open data/title.html
And I open data/search.html in a new window
And I open data/hello.txt as a URL
Then the session should look like:
windows:
- tabs:
- history:
- url: about:blank
- url: http://localhost:*/data/title.html
- tabs:
- history:
- url: http://localhost:*/data/search.html
- history:
- url: http://localhost:*/data/hello.txt
Scenario: Using new-instance-open-target.window = first-opened
When I set general -> new-instance-open-target to tab
And I set general -> new-instance-open-target.window to first-opened
And I open data/title.html
And I open data/search.html in a new window
And I open data/hello.txt as a URL
Then the session should look like:
windows:
- tabs:
- history:
- url: about:blank
- url: http://localhost:*/data/title.html
- history:
- url: http://localhost:*/data/hello.txt
- tabs:
- history:
- url: http://localhost:*/data/search.html
# issue #1060
Scenario: Using target.window = first-opened after tab-detach
When I set general -> new-instance-open-target to tab
And I set general -> new-instance-open-target.window to first-opened
And I open data/title.html
And I open data/search.html in a new tab
And I run :tab-detach
And I open data/hello.txt as a URL
Then the session should look like:
windows:
- tabs:
- history:
- url: about:blank
- url: http://localhost:*/data/title.html
- history:
- url: http://localhost:*/data/hello.txt
- tabs:
- history:
- url: http://localhost:*/data/search.html
Scenario: Opening a new qutebrowser instance with no parameters
When I set general -> new-instance-open-target to tab
And I set general -> startpage to about:blank
And I open data/title.html
And I spawn a new window
And I wait until about:blank is loaded
Then the session should look like:
windows:
- tabs:
- history:
- url: about:blank
- url: http://localhost:*/data/title.html
- tabs:
- history:
- url: about:blank

View File

@ -0,0 +1,30 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
import pytest_bdd as bdd
bdd.scenarios('invoke.feature')
@bdd.when(bdd.parsers.parse("I spawn a new window"))
def invoke_with(quteproc):
"""Spawn a new window via IPC call."""
quteproc.log_summary("Create a new window")
quteproc.send_ipc([], target_arg='window')
quteproc.wait_for(category='init', module='app',
function='_open_startpage', message='Opening startpage')

View File

@ -365,6 +365,15 @@ class QuteProc(testprocess.Process):
finally:
super().after_test()
def send_ipc(self, commands, target_arg=''):
"""Send a raw command to the running IPC socket."""
time.sleep(self._delay / 1000)
assert self._ipc_socket is not None
ipc.send_to_running_instance(self._ipc_socket, commands, target_arg)
self.wait_for(category='ipc', module='ipc', function='on_ready_read',
message='Read from socket *')
def send_cmd(self, command, count=None, invalid=False, *, escape=True):
"""Send a command to the running qutebrowser instance.
@ -379,18 +388,13 @@ class QuteProc(testprocess.Process):
summary += ' (count {})'.format(count)
self.log_summary(summary)
assert self._ipc_socket is not None
time.sleep(self._delay / 1000)
if escape:
command = command.replace('\\', r'\\')
if count is not None:
command = ':{}:{}'.format(count, command.lstrip(':'))
ipc.send_to_running_instance(self._ipc_socket, [command],
target_arg='')
self.send_ipc([command])
if not invalid:
self.wait_for(category='commands', module='command',
function='run', message='command called: *')
@ -418,18 +422,22 @@ class QuteProc(testprocess.Process):
yield
self.set_setting(sect, opt, old_value)
def open_path(self, path, *, new_tab=False, new_window=False, port=None,
https=False, wait=True):
def open_path(self, path, *, new_tab=False, new_window=False, as_url=False,
port=None, https=False, wait=True):
"""Open the given path on the local webserver in qutebrowser."""
url = self.path_to_url(path, port=port, https=https)
self.open_url(url, new_tab=new_tab, new_window=new_window, wait=wait)
self.open_url(url, new_tab=new_tab, new_window=new_window,
as_url=as_url, wait=wait)
def open_url(self, url, *, new_tab=False, new_window=False, wait=True):
def open_url(self, url, *, new_tab=False, new_window=False, as_url=False,
wait=True):
"""Open the given url in qutebrowser."""
if new_tab and new_window:
raise ValueError("new_tab and new_window given!")
if new_tab:
if as_url:
self.send_cmd(url, invalid=True)
elif new_tab:
self.send_cmd(':open -t ' + url)
elif new_window:
self.send_cmd(':open -w ' + url)