From 0557fea79e50086fdcef6b51fa1da4eeda28000b Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 18 Aug 2016 21:36:43 +0200 Subject: [PATCH] Use QApplication.sendEvent instead of postEvent From the QApplication.postEvent docs: http://doc.qt.io/qt-5/qcoreapplication.html#postEvent The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted. It is not safe to access the event after it has been posted. We can't reliably guarantee that from Python, so we need to use sendEvent instead. --- qutebrowser/browser/browsertab.py | 2 +- qutebrowser/browser/commands.py | 8 ++++---- qutebrowser/browser/webelem.py | 4 ++-- qutebrowser/browser/webengine/webenginetab.py | 10 ++++------ qutebrowser/browser/webkit/webkittab.py | 6 ++---- tests/end2end/features/scroll.feature | 5 +++++ tests/unit/utils/test_debug.py | 2 +- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 8e6b30d25..0c86da8f9 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -562,7 +562,7 @@ class AbstractTab(QWidget): self._load_status = val self.load_status_changed.emit(val.name) - def post_event(self, evt): + def send_event(self, evt): """Send the given event to the underlying widget.""" raise NotImplementedError diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 2ee90d843..6b2bcc2ff 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -1953,8 +1953,8 @@ class CommandDispatcher: window = QApplication.focusWindow() if window is None: raise cmdexc.CommandError("No focused window!") - QApplication.postEvent(window, press_event) - QApplication.postEvent(window, release_event) + QApplication.sendEvent(window, press_event) + QApplication.sendEvent(window, release_event) else: try: tab = objreg.get('tab', scope='tab', tab='current') @@ -1962,8 +1962,8 @@ class CommandDispatcher: raise cmdexc.CommandError("No focused webview!") tab = self._current_widget() - tab.post_event(press_event) - tab.post_event(release_event) + tab.send_event(press_event) + tab.send_event(release_event) @cmdutils.register(instance='command-dispatcher', scope='window', debug=True) diff --git a/qutebrowser/browser/webelem.py b/qutebrowser/browser/webelem.py index 31f4f0c57..bf9a5da4d 100644 --- a/qutebrowser/browser/webelem.py +++ b/qutebrowser/browser/webelem.py @@ -384,7 +384,7 @@ class AbstractWebElement(collections.abc.MutableMapping): ] for evt in events: - self._tab.post_event(evt) + self._tab.send_event(evt) def after_click(): """Move cursor to end and reset override_target after clicking.""" @@ -398,4 +398,4 @@ class AbstractWebElement(collections.abc.MutableMapping): pos = self._mouse_pos() event = QMouseEvent(QEvent.MouseMove, pos, Qt.NoButton, Qt.NoButton, Qt.NoModifier) - self._tab.post_event(event) + self._tab.send_event(event) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index f43622208..acc3c19ee 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -201,8 +201,8 @@ class WebEngineScroller(browsertab.AbstractScroller): press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0) release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier, 0, 0, 0) for _ in range(count): - self._tab.post_event(press_evt) - self._tab.post_event(release_evt) + self._tab.send_event(press_evt) + self._tab.send_event(release_evt) @pyqtSlot() def _update_pos(self): @@ -523,8 +523,6 @@ class WebEngineTab(browsertab.AbstractTab): except AttributeError: log.stub('contentsSizeChanged, on Qt < 5.7') - def post_event(self, evt): - # If we get a segfault here, we might want to try sendEvent - # instead. + def send_event(self, evt): recipient = self._widget.focusProxy() - QApplication.postEvent(recipient, evt) + QApplication.sendEvent(recipient, evt) diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index bd7f0a0e2..1d4d36a02 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -696,7 +696,5 @@ class WebKitTab(browsertab.AbstractTab): frame.initialLayoutCompleted.connect(self._on_history_trigger) page.link_clicked.connect(self._on_link_clicked) - def post_event(self, evt): - # If we get a segfault here, we might want to try sendEvent - # instead. - QApplication.postEvent(self._widget, evt) + def send_event(self, evt): + QApplication.sendEvent(self._widget, evt) diff --git a/tests/end2end/features/scroll.feature b/tests/end2end/features/scroll.feature index 4468ea35b..dec0ddce2 100644 --- a/tests/end2end/features/scroll.feature +++ b/tests/end2end/features/scroll.feature @@ -72,6 +72,11 @@ Feature: Scrolling And I run :scroll left Then the page should not be scrolled + # causes segfault with postEvent instead of sendEvent + Scenario: Scrolling down with count 10 + When I run :scroll down with count 10 + Then no crash should happen + Scenario: Scrolling with page down When I run :scroll page-down Then the page should be scrolled vertically diff --git a/tests/unit/utils/test_debug.py b/tests/unit/utils/test_debug.py index 035bd3e08..7b00502f7 100644 --- a/tests/unit/utils/test_debug.py +++ b/tests/unit/utils/test_debug.py @@ -39,7 +39,7 @@ class EventObject(QObject): def test_log_events(qapp, caplog): obj = EventObject() - qapp.postEvent(obj, QEvent(QEvent.User)) + qapp.sendEvent(obj, QEvent(QEvent.User)) qapp.processEvents() assert len(caplog.records) == 1 assert caplog.records[0].msg == 'Event in test_debug.EventObject: User'