Use QApplication.postEvent again
We had some funny segfaults reported during scrolling (i.e. with QApplication.sendEvent), and some code already had to use postpone=True so there was no segfault... So now we're back to postEvent again, and eliminated the main reason for segfaults with it, which was re-using (and -posting) events which had already been posted. At least during tests this seems to run stable, let's hope it helps for the people having crashes as well.
This commit is contained in:
parent
de03feabfe
commit
fff777404b
@ -595,18 +595,20 @@ class AbstractTab(QWidget):
|
|||||||
"""Return the widget events should be sent to."""
|
"""Return the widget events should be sent to."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def send_event(self, evt, *, postpone=False):
|
def send_event(self, evt):
|
||||||
"""Send the given event to the underlying widget.
|
"""Send the given event to the underlying widget.
|
||||||
|
|
||||||
Args:
|
The event will be sent via QApplication.postEvent.
|
||||||
postpone: Postpone the event to be handled later instead of
|
Note that a posted event may not be re-used in any way!
|
||||||
immediately. Using this might cause crashes in Qt.
|
|
||||||
"""
|
"""
|
||||||
|
# This only gives us some mild protection against re-using events, but
|
||||||
|
# it's certainly better than a segfault.
|
||||||
|
if getattr(evt, 'posted', False):
|
||||||
|
raise AssertionError("Can't re-use an event which was already "
|
||||||
|
"posted!")
|
||||||
recipient = self._event_target()
|
recipient = self._event_target()
|
||||||
if postpone:
|
evt.posted = True
|
||||||
QApplication.postEvent(recipient, evt)
|
QApplication.postEvent(recipient, evt)
|
||||||
else:
|
|
||||||
QApplication.sendEvent(recipient, evt)
|
|
||||||
|
|
||||||
@pyqtSlot(QUrl)
|
@pyqtSlot(QUrl)
|
||||||
def _on_link_clicked(self, url):
|
def _on_link_clicked(self, url):
|
||||||
|
@ -1974,8 +1974,8 @@ class CommandDispatcher:
|
|||||||
window = QApplication.focusWindow()
|
window = QApplication.focusWindow()
|
||||||
if window is None:
|
if window is None:
|
||||||
raise cmdexc.CommandError("No focused window!")
|
raise cmdexc.CommandError("No focused window!")
|
||||||
QApplication.sendEvent(window, press_event)
|
QApplication.postEvent(window, press_event)
|
||||||
QApplication.sendEvent(window, release_event)
|
QApplication.postEvent(window, release_event)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
tab = objreg.get('tab', scope='tab', tab='current')
|
tab = objreg.get('tab', scope='tab', tab='current')
|
||||||
|
@ -376,9 +376,7 @@ class AbstractWebElement(collections.abc.MutableMapping):
|
|||||||
]
|
]
|
||||||
|
|
||||||
for evt in events:
|
for evt in events:
|
||||||
# For some reason, postpone=True is needed here to *not* cause
|
self._tab.send_event(evt)
|
||||||
# segfaults in misc.feature because of :fake-key later...
|
|
||||||
self._tab.send_event(evt, postpone=True)
|
|
||||||
|
|
||||||
def after_click():
|
def after_click():
|
||||||
"""Move cursor to end and reset override_target after clicking."""
|
"""Move cursor to end and reset override_target after clicking."""
|
||||||
|
@ -214,9 +214,9 @@ class WebEngineScroller(browsertab.AbstractScroller):
|
|||||||
|
|
||||||
def _key_press(self, key, count=1):
|
def _key_press(self, key, count=1):
|
||||||
# FIXME:qtwebengine Abort scrolling if the minimum/maximum was reached.
|
# FIXME:qtwebengine Abort scrolling if the minimum/maximum was reached.
|
||||||
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):
|
for _ in range(count):
|
||||||
|
press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0)
|
||||||
|
release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier, 0, 0, 0)
|
||||||
self._tab.send_event(press_evt)
|
self._tab.send_event(press_evt)
|
||||||
self._tab.send_event(release_evt)
|
self._tab.send_event(release_evt)
|
||||||
|
|
||||||
|
@ -409,14 +409,15 @@ class WebKitScroller(browsertab.AbstractScroller):
|
|||||||
|
|
||||||
def _key_press(self, key, count=1, getter_name=None, direction=None):
|
def _key_press(self, key, count=1, getter_name=None, direction=None):
|
||||||
frame = self._widget.page().mainFrame()
|
frame = self._widget.page().mainFrame()
|
||||||
press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0)
|
|
||||||
release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier, 0, 0, 0)
|
|
||||||
getter = None if getter_name is None else getattr(frame, getter_name)
|
getter = None if getter_name is None else getattr(frame, getter_name)
|
||||||
|
|
||||||
# FIXME:qtwebengine needed?
|
# FIXME:qtwebengine needed?
|
||||||
# self._widget.setFocus()
|
# self._widget.setFocus()
|
||||||
|
|
||||||
for _ in range(count):
|
for _ in range(count):
|
||||||
|
press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0)
|
||||||
|
release_evt = QKeyEvent(QEvent.KeyRelease, key, Qt.NoModifier,
|
||||||
|
0, 0, 0)
|
||||||
# Abort scrolling if the minimum/maximum was reached.
|
# Abort scrolling if the minimum/maximum was reached.
|
||||||
if (getter is not None and
|
if (getter is not None and
|
||||||
frame.scrollBarValue(direction) == getter(direction)):
|
frame.scrollBarValue(direction) == getter(direction)):
|
||||||
|
@ -84,7 +84,6 @@ Feature: Scrolling
|
|||||||
And I wait until the scroll position changed to 0/0
|
And I wait until the scroll position changed to 0/0
|
||||||
Then the page should not be scrolled
|
Then the page should not be scrolled
|
||||||
|
|
||||||
# causes segfault with postEvent instead of sendEvent
|
|
||||||
Scenario: Scrolling down with count 10
|
Scenario: Scrolling down with count 10
|
||||||
When I run :scroll down with count 10
|
When I run :scroll down with count 10
|
||||||
Then no crash should happen
|
Then no crash should happen
|
||||||
|
Loading…
Reference in New Issue
Block a user