From fe11e25430f4def91fd702e478ff73cebe60dc7a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 19 Aug 2016 18:38:07 +0200 Subject: [PATCH] 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. --- qutebrowser/browser/browsertab.py | 9 ++++++++- qutebrowser/browser/mouse.py | 12 ++++++++++-- qutebrowser/browser/webengine/webenginetab.py | 3 +++ qutebrowser/browser/webkit/webkittab.py | 2 ++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index d218deebc..cfc5b385d 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -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? diff --git a/qutebrowser/browser/mouse.py b/qutebrowser/browser/mouse.py index a08b693eb..a91f8961b 100644 --- a/qutebrowser/browser/mouse.py +++ b/qutebrowser/browser/mouse.py @@ -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) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 6ec26c3df..9ff965600 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -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) diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index a8895f6e5..12f32de97 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -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)