Ignore mouse events going to non-main widgets

When we hide the context menu on QtWebEngine, we get a mouse event
relative to the QMenu in the filter, which means tab.elements.at_pos
will get called with a negative position (and thus assert) or at least a
wrong position.
This commit is contained in:
Florian Bruhin 2016-08-19 18:38:07 +02:00
parent dec0f0753d
commit fe11e25430
4 changed files with 23 additions and 3 deletions

View File

@ -470,6 +470,10 @@ class AbstractTab(QWidget):
We use this to unify QWebView and QWebEngineView.
Class attributes:
WIDGET_CLASS: The class of the main widget recieving events.
Needs to be overridden by subclasses.
Attributes:
history: The AbstractHistory for the current tab.
registry: The ObjectRegistry associated with this tab.
@ -503,6 +507,8 @@ class AbstractTab(QWidget):
contents_size_changed = pyqtSignal(QSizeF)
add_history_item = pyqtSignal(QUrl, QUrl, str) # url, requested url, title
WIDGET_CLASS = None
def __init__(self, win_id, parent=None):
self.win_id = win_id
self.tab_id = next(tab_id_gen)
@ -529,7 +535,8 @@ class AbstractTab(QWidget):
self._progress = 0
self._has_ssl_errors = False
self._load_status = usertypes.LoadStatus.none
self._mouse_event_filter = mouse.MouseEventFilter(self, parent=self)
self._mouse_event_filter = mouse.MouseEventFilter(
self, widget_class=self.WIDGET_CLASS, parent=self)
self.backend = None
# FIXME:qtwebengine Should this be public api via self.hints?

View File

@ -64,6 +64,8 @@ class MouseEventFilter(QObject):
"""Handle mouse events on a tab.
Attributes:
_widget_class: The class of the main widget getting the events.
All other events are ignored.
_tab: The browsertab object this filter is installed on.
_handlers: A dict of handler functions for the handled events.
_ignore_wheel_event: Whether to ignore the next wheelEvent.
@ -71,8 +73,9 @@ class MouseEventFilter(QObject):
done when the mouse is released.
"""
def __init__(self, tab, parent=None):
def __init__(self, tab, *, widget_class, parent=None):
super().__init__(parent)
self._widget_class = widget_class
self._tab = tab
self._handlers = {
QEvent.MouseButtonPress: self._handle_mouse_press,
@ -219,9 +222,14 @@ class MouseEventFilter(QObject):
self._tab.data.open_target = usertypes.ClickTarget.normal
log.mouse.debug("Normal click, setting normal target")
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
if not isinstance(obj, self._widget_class):
log.mouse.debug("Ignoring {} to {} which is not an instance of "
"{}".format(event.__class__.__name__, obj,
self._widget_class))
return False
return self._handlers[evtype](event)

View File

@ -27,6 +27,7 @@ import functools
from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint, QUrl
from PyQt5.QtGui import QKeyEvent, QIcon
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWidgets import QOpenGLWidget
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript
# pylint: enable=no-name-in-module,import-error,useless-suppression
@ -376,6 +377,8 @@ class WebEngineTab(browsertab.AbstractTab):
"""A QtWebEngine tab in the browser."""
WIDGET_CLASS = QOpenGLWidget
def __init__(self, win_id, mode_manager, parent=None):
super().__init__(win_id)
widget = webview.WebEngineView(tabdata=self.data)

View File

@ -574,6 +574,8 @@ class WebKitTab(browsertab.AbstractTab):
"""A QtWebKit tab in the browser."""
WIDGET_CLASS = webview.WebView
def __init__(self, win_id, mode_manager, parent=None):
super().__init__(win_id)
widget = webview.WebView(win_id, self.tab_id, tab=self)