mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-09 17:48:21 +02:00
Merge pull request #11077 from jherico/overlay_event_crashes
Fix overlay event handling thread issues
This commit is contained in:
commit
cfd9f8b64e
3 changed files with 41 additions and 63 deletions
|
@ -706,27 +706,27 @@ bool Overlays::isAddedOverlay(OverlayID id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event) {
|
void Overlays::sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event) {
|
||||||
emit mousePressOnOverlay(overlayID, event);
|
QMetaObject::invokeMethod(this, "mousePressOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event) {
|
void Overlays::sendMouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event) {
|
||||||
emit mouseReleaseOnOverlay(overlayID, event);
|
QMetaObject::invokeMethod(this, "mouseReleaseOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event) {
|
void Overlays::sendMouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event) {
|
||||||
emit mouseMoveOnOverlay(overlayID, event);
|
QMetaObject::invokeMethod(this, "mouseMoveOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendHoverEnterOverlay(OverlayID id, PointerEvent event) {
|
void Overlays::sendHoverEnterOverlay(OverlayID id, PointerEvent event) {
|
||||||
emit hoverEnterOverlay(id, event);
|
QMetaObject::invokeMethod(this, "hoverEnterOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendHoverOverOverlay(OverlayID id, PointerEvent event) {
|
void Overlays::sendHoverOverOverlay(OverlayID id, PointerEvent event) {
|
||||||
emit hoverOverOverlay(id, event);
|
QMetaObject::invokeMethod(this, "hoverOverOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent event) {
|
void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent event) {
|
||||||
emit hoverLeaveOverlay(id, event);
|
QMetaObject::invokeMethod(this, "hoverLeaveOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayID Overlays::getKeyboardFocusOverlay() {
|
OverlayID Overlays::getKeyboardFocusOverlay() {
|
||||||
|
|
|
@ -100,30 +100,14 @@ Web3DOverlay::~Web3DOverlay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_webSurface->pause();
|
_webSurface->pause();
|
||||||
_webSurface->disconnect(_connection);
|
auto overlays = &(qApp->getOverlays());
|
||||||
|
QObject::disconnect(overlays, &Overlays::mousePressOnOverlay, this, nullptr);
|
||||||
QObject::disconnect(_mousePressConnection);
|
QObject::disconnect(overlays, &Overlays::mouseReleaseOnOverlay, this, nullptr);
|
||||||
_mousePressConnection = QMetaObject::Connection();
|
QObject::disconnect(overlays, &Overlays::mouseMoveOnOverlay, this, nullptr);
|
||||||
QObject::disconnect(_mouseReleaseConnection);
|
QObject::disconnect(overlays, &Overlays::hoverLeaveOverlay, this, nullptr);
|
||||||
_mouseReleaseConnection = QMetaObject::Connection();
|
QObject::disconnect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
||||||
QObject::disconnect(_mouseMoveConnection);
|
QObject::disconnect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
||||||
_mouseMoveConnection = QMetaObject::Connection();
|
DependencyManager::get<OffscreenQmlSurfaceCache>()->release(QML, _webSurface);
|
||||||
QObject::disconnect(_hoverLeaveConnection);
|
|
||||||
_hoverLeaveConnection = QMetaObject::Connection();
|
|
||||||
|
|
||||||
QObject::disconnect(_emitScriptEventConnection);
|
|
||||||
_emitScriptEventConnection = QMetaObject::Connection();
|
|
||||||
QObject::disconnect(_webEventReceivedConnection);
|
|
||||||
_webEventReceivedConnection = QMetaObject::Connection();
|
|
||||||
|
|
||||||
// The lifetime of the QML surface MUST be managed by the main thread
|
|
||||||
// Additionally, we MUST use local variables copied by value, rather than
|
|
||||||
// member variables, since they would implicitly refer to a this that
|
|
||||||
// is no longer valid
|
|
||||||
auto webSurface = _webSurface;
|
|
||||||
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
|
|
||||||
DependencyManager::get<OffscreenQmlSurfaceCache>()->release(QML, webSurface);
|
|
||||||
});
|
|
||||||
_webSurface.reset();
|
_webSurface.reset();
|
||||||
}
|
}
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
@ -153,6 +137,9 @@ QString Web3DOverlay::pickURL() {
|
||||||
|
|
||||||
|
|
||||||
void Web3DOverlay::loadSourceURL() {
|
void Web3DOverlay::loadSourceURL() {
|
||||||
|
if (!_webSurface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QUrl sourceUrl(_url);
|
QUrl sourceUrl(_url);
|
||||||
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
|
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
|
||||||
|
@ -252,10 +239,11 @@ void Web3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_mousePressConnection = connect(&(qApp->getOverlays()), &Overlays::mousePressOnOverlay, this, forwardPointerEvent, Qt::DirectConnection);
|
auto overlays = &(qApp->getOverlays());
|
||||||
_mouseReleaseConnection = connect(&(qApp->getOverlays()), &Overlays::mouseReleaseOnOverlay, this, forwardPointerEvent, Qt::DirectConnection);
|
QObject::connect(overlays, &Overlays::mousePressOnOverlay, this, forwardPointerEvent);
|
||||||
_mouseMoveConnection = connect(&(qApp->getOverlays()), &Overlays::mouseMoveOnOverlay, this, forwardPointerEvent, Qt::DirectConnection);
|
QObject::connect(overlays, &Overlays::mouseReleaseOnOverlay, this, forwardPointerEvent);
|
||||||
_hoverLeaveConnection = connect(&(qApp->getOverlays()), &Overlays::hoverLeaveOverlay, this, [=](OverlayID overlayID, const PointerEvent& event) {
|
QObject::connect(overlays, &Overlays::mouseMoveOnOverlay, this, forwardPointerEvent);
|
||||||
|
QObject::connect(overlays, &Overlays::hoverLeaveOverlay, this, [=](OverlayID overlayID, const PointerEvent& event) {
|
||||||
auto self = weakSelf.lock();
|
auto self = weakSelf.lock();
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return;
|
return;
|
||||||
|
@ -265,10 +253,10 @@ void Web3DOverlay::render(RenderArgs* args) {
|
||||||
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
||||||
forwardPointerEvent(overlayID, event);
|
forwardPointerEvent(overlayID, event);
|
||||||
}
|
}
|
||||||
}, Qt::DirectConnection);
|
});
|
||||||
|
|
||||||
_emitScriptEventConnection = connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
||||||
_webEventReceivedConnection = connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
||||||
} else {
|
} else {
|
||||||
if (_currentMaxFPS != _desiredMaxFPS) {
|
if (_currentMaxFPS != _desiredMaxFPS) {
|
||||||
setMaxFPS(_desiredMaxFPS);
|
setMaxFPS(_desiredMaxFPS);
|
||||||
|
@ -438,11 +426,11 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
|
||||||
QList<QTouchEvent::TouchPoint> touchPoints;
|
QList<QTouchEvent::TouchPoint> touchPoints;
|
||||||
touchPoints.push_back(point);
|
touchPoints.push_back(point);
|
||||||
|
|
||||||
QTouchEvent* touchEvent = new QTouchEvent(touchType, &_touchDevice, event.getKeyboardModifiers());
|
QTouchEvent touchEvent(touchType, &_touchDevice, event.getKeyboardModifiers());
|
||||||
touchEvent->setWindow(_webSurface->getWindow());
|
touchEvent.setWindow(_webSurface->getWindow());
|
||||||
touchEvent->setTarget(_webSurface->getRootItem());
|
touchEvent.setTarget(_webSurface->getRootItem());
|
||||||
touchEvent->setTouchPoints(touchPoints);
|
touchEvent.setTouchPoints(touchPoints);
|
||||||
touchEvent->setTouchPointStates(touchPointState);
|
touchEvent.setTouchPointStates(touchPointState);
|
||||||
|
|
||||||
// Send mouse events to the Web surface so that HTML dialog elements work with mouse press and hover.
|
// Send mouse events to the Web surface so that HTML dialog elements work with mouse press and hover.
|
||||||
// FIXME: Scroll bar dragging is a bit unstable in the tablet (content can jump up and down at times).
|
// FIXME: Scroll bar dragging is a bit unstable in the tablet (content can jump up and down at times).
|
||||||
|
@ -452,16 +440,16 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
|
||||||
// receive mouse events
|
// receive mouse events
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||||
if (event.getType() == PointerEvent::Move) {
|
if (event.getType() == PointerEvent::Move) {
|
||||||
QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
||||||
QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &touchEvent);
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
|
||||||
if (event.getType() == PointerEvent::Move) {
|
if (event.getType() == PointerEvent::Move) {
|
||||||
QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
||||||
QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -505,8 +493,8 @@ void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMouseEvent* mouseEvent = new QMouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
QMouseEvent mouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
||||||
QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent);
|
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
|
@ -608,6 +596,9 @@ void Web3DOverlay::setScriptURL(const QString& scriptURL) {
|
||||||
_scriptURL = scriptURL;
|
_scriptURL = scriptURL;
|
||||||
if (_webSurface) {
|
if (_webSurface) {
|
||||||
AbstractViewStateInterface::instance()->postLambdaEvent([this, scriptURL] {
|
AbstractViewStateInterface::instance()->postLambdaEvent([this, scriptURL] {
|
||||||
|
if (!_webSurface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_webSurface->getRootItem()->setProperty("scriptURL", scriptURL);
|
_webSurface->getRootItem()->setProperty("scriptURL", scriptURL);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -631,9 +622,5 @@ Web3DOverlay* Web3DOverlay::createClone() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Web3DOverlay::emitScriptEvent(const QVariant& message) {
|
void Web3DOverlay::emitScriptEvent(const QVariant& message) {
|
||||||
if (QThread::currentThread() != thread()) {
|
QMetaObject::invokeMethod(this, "scriptEventReceived", Q_ARG(QVariant, message));
|
||||||
QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, message));
|
|
||||||
} else {
|
|
||||||
emit scriptEventReceived(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,6 @@ signals:
|
||||||
private:
|
private:
|
||||||
InputMode _inputMode { Touch };
|
InputMode _inputMode { Touch };
|
||||||
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
||||||
QMetaObject::Connection _connection;
|
|
||||||
gpu::TexturePointer _texture;
|
gpu::TexturePointer _texture;
|
||||||
QString _url;
|
QString _url;
|
||||||
QString _scriptURL;
|
QString _scriptURL;
|
||||||
|
@ -88,14 +87,6 @@ private:
|
||||||
uint8_t _currentMaxFPS { 0 };
|
uint8_t _currentMaxFPS { 0 };
|
||||||
|
|
||||||
bool _mayNeedResize { false };
|
bool _mayNeedResize { false };
|
||||||
|
|
||||||
QMetaObject::Connection _mousePressConnection;
|
|
||||||
QMetaObject::Connection _mouseReleaseConnection;
|
|
||||||
QMetaObject::Connection _mouseMoveConnection;
|
|
||||||
QMetaObject::Connection _hoverLeaveConnection;
|
|
||||||
|
|
||||||
QMetaObject::Connection _emitScriptEventConnection;
|
|
||||||
QMetaObject::Connection _webEventReceivedConnection;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Web3DOverlay_h
|
#endif // hifi_Web3DOverlay_h
|
||||||
|
|
Loading…
Reference in a new issue