Skip to content

Commit

Permalink
Install MouseEventFilter on new WebEngine children
Browse files Browse the repository at this point in the history
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 64afc56
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 17 deletions.
9 changes: 4 additions & 5 deletions qutebrowser/browser/browsertab.py
Expand Up @@ -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
Expand All @@ -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."""
Expand Down
34 changes: 30 additions & 4 deletions qutebrowser/browser/mouse.py
Expand Up @@ -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."""
Expand All @@ -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)
Expand Down Expand Up @@ -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)
11 changes: 8 additions & 3 deletions qutebrowser/browser/webengine/webenginetab.py
Expand Up @@ -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

Expand Down Expand Up @@ -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([
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions qutebrowser/browser/webkit/webkittab.py
Expand Up @@ -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)
Expand Down
3 changes: 0 additions & 3 deletions tests/unit/browser/test_tab.py
Expand Up @@ -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')
Expand Down

0 comments on commit 64afc56

Please sign in to comment.