diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 05b5673d76c..eda0f62ee2d 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -485,9 +485,6 @@ def __init__(self, win_id, parent=None): self._mouse_event_filter = mouse.MouseEventFilter(self, parent=self) self.backend = None - def _event_filter_target(self): - raise NotImplementedError - def _set_widget(self, widget): # pylint: disable=protected-access self._widget = widget @@ -499,8 +496,10 @@ def _set_widget(self, widget): self.search._widget = widget self.printing._widget = widget widget.mouse_wheel_zoom.connect(self.zoom._on_mouse_wheel_zoom) - event_filter_target = self._event_filter_target() - event_filter_target.installEventFilter(self._mouse_event_filter) + self._install_event_filter() + + def _install_event_filter(self): + raise NotImplementedError def _set_load_status(self, val): """Setter for load_status.""" diff --git a/qutebrowser/browser/mouse.py b/qutebrowser/browser/mouse.py index 3bd3bf32b41..d080f1f755f 100644 --- a/qutebrowser/browser/mouse.py +++ b/qutebrowser/browser/mouse.py @@ -21,12 +21,38 @@ from qutebrowser.config import config -from qutebrowser.utils import message +from qutebrowser.utils import message, debug, log from PyQt5.QtCore import QObject, QEvent, Qt +class ChildEventFilter(QObject): + + """An event filter re-adding MouseEventFilter on ChildEvent. + + This is needed because QtWebEngine likes to randomly change its + focusProxy... + + FIXME:qtwebengine Add a test for this happening + """ + + def __init__(self, eventfilter, widget, parent=None): + super().__init__(parent) + self._filter = eventfilter + assert widget is not None + self._widget = widget + + def eventFilter(self, obj, event): + if event.type() == QEvent.ChildAdded: + child = event.child() + log.mouse.debug("{} got new child {}, installing filter".format( + obj, child)) + assert obj is self._widget + child.installEventFilter(self._filter) + return False + + class MouseEventFilter(QObject): """Handle mouse events on a tab.""" @@ -38,7 +64,7 @@ def __init__(self, tab, parent=None): QEvent.MouseButtonPress: self._handle_mouse_press, } - def _handle_mouse_press(self, e): + def _handle_mouse_press(self, _obj, e): """Handle pressing of a mouse button.""" is_rocker_gesture = (config.get('input', 'rocker-gestures') and e.buttons() == Qt.LeftButton | Qt.RightButton) @@ -69,9 +95,9 @@ def _mousepress_backforward(self, e): message.error(self._tab.win_id, "At end of history.", immediately=True) - def eventFilter(self, _obj, event): + def eventFilter(self, obj, event): """Filter events going to a QWeb(Engine)View.""" evtype = event.type() if evtype not in self._handlers: return False - return self._handlers[evtype](event) + return self._handlers[evtype](obj, event) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 93e1275d9d9..f74adadf341 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -31,7 +31,7 @@ from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript # pylint: enable=no-name-in-module,import-error,useless-suppression -from qutebrowser.browser import browsertab +from qutebrowser.browser import browsertab, mouse from qutebrowser.browser.webengine import webview, webengineelem from qutebrowser.utils import usertypes, qtutils, log, javascript, utils @@ -335,6 +335,7 @@ def __init__(self, win_id, mode_manager, parent=None): self.backend = usertypes.Backend.QtWebEngine # init js stuff self._init_js() + self._child_event_filter = None def _init_js(self): js_code = '\n'.join([ @@ -359,8 +360,12 @@ def _init_js(self): # FIXME:qtwebengine what about runsOnSubFrames? page.scripts().insert(script) - def _event_filter_target(self): - return self._widget.focusProxy() + def _install_event_filter(self): + self._widget.focusProxy().installEventFilter(self._mouse_event_filter) + self._child_event_filter = mouse.ChildEventFilter( + eventfilter=self._mouse_event_filter, widget=self._widget, + parent=self) + self._widget.installEventFilter(self._child_event_filter) def openurl(self, url): self._openurl_prepare(url) diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index 8d47152cd9a..d4fdea2ff16 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -510,8 +510,8 @@ def __init__(self, win_id, mode_manager, parent=None): self.zoom.set_default() self.backend = usertypes.Backend.QtWebKit - def _event_filter_target(self): - return self._widget + def _install_event_filter(self): + self._widget.installEventFilter(self._mouse_event_filter) def openurl(self, url): self._openurl_prepare(url) diff --git a/tests/unit/browser/test_tab.py b/tests/unit/browser/test_tab.py index cd6e9b374dc..2f11b07abf3 100644 --- a/tests/unit/browser/test_tab.py +++ b/tests/unit/browser/test_tab.py @@ -107,9 +107,6 @@ def __init__(self, win_id, parent=None): self.search = browsertab.AbstractSearch(parent=self) self.printing = browsertab.AbstractPrinting() - def _event_filter_target(self): - return self._widget - @pytest.mark.skipif(PYQT_VERSION < 0x050600, reason='Causes segfaults, see #1638')