Repository: qutebrowser/qutebrowser

Issue:
After opening a background tab, scrolling happens in the wrong tab.
When I open a tab in the background using the F binding, and then try to navigate the page with arrows or PgUp/PgDown the current page does not move. By hitting : and then escape it regains focus.

On moving to the newly opened tab, it appears that it has received the arrow keys instead.


### version info
qutebrowser v0.9.1
Git commit: v0.9.0-277-g79d22f250 (2017-02-17 07:02:57 +0100)
Backend: QtWebEngine



Discussion:
I can't reproduce this. What Qt version are you on? Can you reproduce it with `--temp-basedir`? Does it also happen when middle-/ctrl-clicking links? Can you try on the latest git master (something changed about how hints are opened there)?
I forgot to mention that I have set tabs background-tabs true (I forgot that it wasn't the default).
The problem also exists with the latest git master, and with --temp-basedir.
It does not happen when ctrl-clicking links.

### Updated and more complete version info

qutebrowser v0.9.1
Git commit: v0.9.0-292-g0b94f2ed8 (2017-02-18 00:46:55 +0100)
Backend: QtWebEngine

CPython: 3.6.0
Qt: 5.8.0
PyQt: 5.7.1

sip: 4.19
colorama: 0.3.7
pypeg2: 2.15
jinja2: 2.9.5
pygments: 2.2.0
yaml: 3.12
cssutils: 1.0.1 $Id$
typing: yes
PyQt5.QtWebEngineWidgets: yes
pdf.js: no
Webkit: 538.1
SSL: OpenSSL 1.0.2k  26 Jan 2017

Style: QFusionStyle
Platform: Linux-4.9.8-1-ARCH-x86_64-with-arch, 64bit
Frozen: False
Imported from /usr/lib/python3.6/site-packages/qutebrowser
OS Version: 

--- /etc/lsb-release ---
LSB_VERSION=1.4
DISTRIB_ID=Arch
DISTRIB_RELEASE=rolling
DISTRIB_DESCRIPTION="Arch Linux"

--- /etc/os-release ---
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
ID_LIKE=archlinux

Reproduced now, though scrolling just doesn't happen at all here, not in the other tab either.
Ok. Strange that you don't get scrolling in any tab, I've tested on several websites and concistently do.
I now do too, no idea why I got different behavior before. Haven't figured out why it happens yet.
Like with #2321, https://codereview.qt-project.org/#/c/184111/ or https://codereview.qt-project.org/#/c/176113/ might be related.
Still reproduces with Qt 5.9
As it isn't mentioned on this issue, yet: when I open a page with `F` and `set tabs background-tabs true`, I can reproduce the problem, but only with the arrow keys. j/k and the scrollwheel all work on the current tab.
So as a workaround you can bind up/down/pgup/pgdown to scroll/scroll-page:
```
bind <up> scroll up
bind <down> scroll down
bind <pgup> scroll-page 0 -1
bind <pgdown> scroll-page 0 +1
```

Is there a way to focus the currently active tab with a command? I can do that for example by clicking the active tab with mouse, but if there would be a command then I could just bind to always execute that after `:open -b`.
@Ape From the original post here:

> By hitting : and then escape it regains focus.

FWIW it's already focused as far as qutebrowser is concerned, but there's something with QtWebEngine going wrong there most likely.
`:` + escape fixes the focus. If that works then there is probably something qutebrowser could do after opening background tabs to workaround this (even if this is really caused by QtWebEngine). This issue is quite annoying and it seems to affect many people (at least the bug has been reported many times).
I agree there's probably some workaround, but those things are usually quite tricky to fix. This also doesn't affect me personally and has multiple workarounds available. As usual, the best way to get something fixed quickly is to contribute, there is only so much I can take care of every given day ;)
This horrible workaround is effective:
```diff
--- qutebrowser/mainwindow/tabbedbrowser.py	2017-12-29 23:21:23.289723961 +1100
+++ qutebrowser/mainwindow/tabbedbrowser.py	2017-12-29 23:21:32.968723672 +1100
@@ -465,6 +465,8 @@
         else:
             self.setCurrentWidget(tab)
 
+        self.currentWidget().setFocus()
+
         tab.show()
         self.new_tab.emit(tab, idx)
         return tab
```
@abrasive Thanks, it seems to work.

@The-Compiler Is this something you would be willing to merge?
Doesn't seem too bad to me - I want to look into it some more, but I'm not opposed to that workaround. However, I'm currently busy with exams, so it might be early February until I get to it. @abrasive, mind to open a pull request with the fix so it doesn't get lost?
Was this fixed? This doesn't seem to occur for me since I upgraded qutebrowser from 1.0 to 1.1.1.
Doesn't seem to be fixed in qutebrowser, but in Qt 5.10. I can still reproduce it on Qt <= 5.9.

Resolving patch:
diff --git a/qutebrowser/browser/mouse.py b/qutebrowser/browser/mouse.py
--- a/qutebrowser/browser/mouse.py
+++ b/qutebrowser/browser/mouse.py
@@ -22,7 +22,7 @@
 from PyQt5.QtCore import QObject, QEvent, Qt, QTimer
 
 from qutebrowser.config import config
-from qutebrowser.utils import message, log, usertypes, qtutils
+from qutebrowser.utils import message, log, usertypes, qtutils, objreg
 from qutebrowser.keyinput import modeman
 
 
@@ -40,11 +40,12 @@ class ChildEventFilter(QObject):
         _widget: The widget expected to send out childEvents.
     """
 
-    def __init__(self, eventfilter, widget, parent=None):
+    def __init__(self, eventfilter, widget, win_id, parent=None):
         super().__init__(parent)
         self._filter = eventfilter
         assert widget is not None
         self._widget = widget
+        self._win_id = win_id
 
     def eventFilter(self, obj, event):
         """Act on ChildAdded events."""
@@ -57,7 +58,22 @@ def eventFilter(self, obj, event):
 
             if qtutils.version_check('5.11', compiled=False, exact=True):
                 # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-68076
-                QTimer.singleShot(0, self._widget.setFocus)
+                pass_modes = [usertypes.KeyMode.command,
+                              usertypes.KeyMode.prompt,
+                              usertypes.KeyMode.yesno]
+                if modeman.instance(self._win_id).mode not in pass_modes:
+                    tabbed_browser = objreg.get('tabbed-browser',
+                                                scope='window',
+                                                window=self._win_id)
+                    current_index = tabbed_browser.widget.currentIndex()
+                    try:
+                        widget_index = tabbed_browser.widget.indexOf(
+                            self._widget.parent())
+                    except RuntimeError:
+                        widget_index = -1
+                    if current_index == widget_index:
+                        QTimer.singleShot(0, self._widget.setFocus)
+
         elif event.type() == QEvent.ChildRemoved:
             child = event.child()
             log.mouse.debug("{}: removed child {}".format(obj, child))
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -769,7 +769,7 @@ def _install_event_filter(self):
             fp.installEventFilter(self._mouse_event_filter)
         self._child_event_filter = mouse.ChildEventFilter(
             eventfilter=self._mouse_event_filter, widget=self._widget,
-            parent=self)
+            win_id=self.win_id, parent=self)
         self._widget.installEventFilter(self._child_event_filter)
 
     @pyqtSlot()
diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py
--- a/qutebrowser/mainwindow/tabbedbrowser.py
+++ b/qutebrowser/mainwindow/tabbedbrowser.py
@@ -22,7 +22,7 @@
 import functools
 
 import attr
-from PyQt5.QtWidgets import QSizePolicy, QWidget
+from PyQt5.QtWidgets import QSizePolicy, QWidget, QApplication
 from PyQt5.QtCore import pyqtSignal, pyqtSlot, QTimer, QUrl
 from PyQt5.QtGui import QIcon
 
@@ -458,6 +458,8 @@ def tabopen(self, url=None, background=None, related=True, idx=None, *,
                           "related {}, idx {}".format(
                               url, background, related, idx))
 
+        prev_focus = QApplication.focusWidget()
+
         if (config.val.tabs.tabs_are_windows and self.widget.count() > 0 and
                 not ignore_tabs_are_windows):
             window = mainwindow.MainWindow(private=self.private)
@@ -487,12 +489,21 @@ def tabopen(self, url=None, background=None, related=True, idx=None, *,
             tab.resize(self.widget.currentWidget().size())
             self.widget.tab_index_changed.emit(self.widget.currentIndex(),
                                                self.widget.count())
+            # Refocus webview in case we lost it by spawning a bg tab
+            self.widget.currentWidget().setFocus()
         else:
             self.widget.setCurrentWidget(tab)
             # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-68076
             # Still seems to be needed with Qt 5.11.1
             tab.setFocus()
 
+        mode = modeman.instance(self._win_id).mode
+        if mode in [usertypes.KeyMode.command, usertypes.KeyMode.prompt,
+                    usertypes.KeyMode.yesno]:
+            # If we were in a command prompt, restore old focus
+            # The above commands need to be run to switch tabs
+            prev_focus.setFocus()
+
         tab.show()
         self.new_tab.emit(tab, idx)
         return tab


Test patch:
diff --git a/tests/end2end/data/hints/link_input.html b/tests/end2end/data/hints/link_input.html
new file mode 100644
--- /dev/null
+++ b/tests/end2end/data/hints/link_input.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Simple link and input</title>
+        <script type="text/javascript">
+          function setup_event_listener() {
+              var elem = document.getElementById('qute-input-existing');
+              console.log(elem);
+              elem.addEventListener('input', function() {
+                  console.log("contents: " + elem.value);
+              });
+          }
+        </script>
+    </head>
+    <body onload="setup_event_listener()">
+        <a href="/data/hello.txt" id="link">Follow me!</a>
+        <form><input id="qute-input"></input></form>
+        With padding:
+        <form><input type="text" style="padding-left: 20px;"></input></form>
+        With existing text (logs to JS)::
+        <form><input id="qute-input-existing" value="existing"></input></form>
+    </body>
+</html>
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
@@ -1250,3 +1250,41 @@ Feature: Tab management
         Then the following tabs should be open:
             - data/numbers/1.txt
             - data/numbers/2.txt (pinned) (active)
+
+
+    Scenario: Focused webview after clicking link in bg
+        When I open data/hints/link_input.html
+        And I run :click-element id qute-input-existing
+        And I wait for "Entering mode KeyMode.insert *" in the log
+        And I run :leave-mode
+        And I hint with args "all tab-bg" and follow a
+        And I wait until data/hello.txt is loaded
+        And I run :enter-mode insert
+        And I run :fake-key -g new
+        Then the javascript message "contents: existingnew" should be logged
+
+    Scenario: Focused webview after opening link in bg
+        When I open data/hints/link_input.html
+        And I run :click-element id qute-input-existing
+        And I wait for "Entering mode KeyMode.insert *" in the log
+        And I run :leave-mode
+        And I open data/hello.txt in a new background tab
+        And I run :enter-mode insert
+        And I run :fake-key -g new
+        Then the javascript message "contents: existingnew" should be logged
+
+    Scenario: Focused prompt after opening link in bg
+        When I open data/hints/link_input.html
+        When I run :set-cmd-text -s :message-info
+        And I open data/hello.txt in a new background tab
+        And I run :fake-key -g hello-world
+        And I run :command-accept
+        Then the message "hello-world" should be shown
+
+    Scenario: Focused prompt after opening link in fg
+        When I open data/hints/link_input.html
+        When I run :set-cmd-text -s :message-info
+        And I open data/hello.txt in a new tab
+        And I run :fake-key -g hello-world
+        And I run :command-accept
+        Then the message "hello-world" should be shown