Permalink
Browse files

Install MouseEventFilter on new WebEngine children

For some reason, when e.g. visiting duckduckgo and then heise.de,
QtWebEngine suddenly gets a new QOpenGLWidget as focusProxy.

We install an extra eventFilter observing the ChildAdded event and
re-adding the MouseEventFilter when that happens.
  • Loading branch information...
The-Compiler committed Aug 10, 2016
1 parent d4f30bd commit 64afc562b60d62446c67814b77b3ff5240ad1287
@@ -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."""
@@ -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)
@@ -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)
@@ -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)
@@ -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')

0 comments on commit 64afc56

Please sign in to comment.