Showing the changes to libraries/script-engine/src/TabletScriptingInterface.cpp (1 of 2 files). Show all
Unified · Split
| @@ -21,6 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <InfoView.h> |
| 22 | 22 | #include "SoundEffect.h" |
| 23 | 23 | |
| 24 | +const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; | |
| 25 | +const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; | |
| 24 | 26 | |
| 25 | 27 | QScriptValue tabletToScriptValue(QScriptEngine* engine, TabletProxy* const &in) { |
| 26 | 28 | return engine->newQObject(in, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); |
| @@ -35,11 +37,11 @@ TabletScriptingInterface::TabletScriptingInterface() { · 8 unmodified lines | ||
| 35 | 37 | } |
| 36 | 38 | |
| 37 | 39 | QObject* TabletScriptingInterface::getSystemToolbarProxy() { |
| 38 | − const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; | |
| 39 | 40 | Qt::ConnectionType connectionType = Qt::AutoConnection; |
| 40 | 41 | if (QThread::currentThread() != _toolbarScriptingInterface->thread()) { |
| 41 | 42 | connectionType = Qt::BlockingQueuedConnection; |
| 42 | 43 | } |
| 44 | + | |
| 43 | 45 | QObject* toolbarProxy = nullptr; |
| 44 | 46 | bool hasResult = QMetaObject::invokeMethod(_toolbarScriptingInterface, "getToolbar", connectionType, Q_RETURN_ARG(QObject*, toolbarProxy), Q_ARG(QString, SYSTEM_TOOLBAR)); |
| 45 | 47 | if (hasResult) { |
| @@ -51,28 +53,38 @@ QObject* TabletScriptingInterface::getSystemToolbarProxy() { · 5 unmodified lines | ||
| 51 | 53 | } |
| 52 | 54 | |
| 53 | 55 | TabletProxy* TabletScriptingInterface::getTablet(const QString& tabletId) { |
| 54 | − | |
| 55 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 56 | − | |
| 57 | − // look up tabletId in the map. | |
| 58 | − auto iter = _tabletProxies.find(tabletId); | |
| 59 | − if (iter != _tabletProxies.end()) { | |
| 60 | − // tablet already exists, just return it. | |
| 61 | − return iter->second; | |
| 62 | − } else { | |
| 63 | − // allocate a new tablet, add it to the map then return it. | |
| 64 | − auto tabletProxy = new TabletProxy(tabletId); | |
| 65 | − tabletProxy->setParent(this); | |
| 66 | − _tabletProxies[tabletId] = tabletProxy; | |
| 67 | − tabletProxy->setToolbarMode(_toolbarMode); | |
| 68 | − return tabletProxy; | |
| 56 | + TabletProxy* tabletProxy = nullptr; | |
| 57 | + { | |
| 58 | + // the only thing guarded should be map mutation | |
| 59 | + // this avoids a deadlock with the Main thread | |
| 60 | + // from Qt::BlockingQueuedEvent invocations later in the call-tree | |
| 61 | + std::lock_guard<std::mutex> guard(_mapMutex); | |
| 62 | + | |
| 63 | + auto iter = _tabletProxies.find(tabletId); | |
| 64 | + if (iter != _tabletProxies.end()) { | |
| 65 | + // tablet already exists | |
| 66 | + return iter->second; | |
| 67 | + } else { | |
| 68 | + // tablet must be created | |
| 69 | + tabletProxy = new TabletProxy(this, tabletId); | |
| 70 | + _tabletProxies[tabletId] = tabletProxy; | |
| 71 | + } | |
| 69 | 72 | } |
| 73 | + | |
| 74 | + assert(tabletProxy); | |
| 75 | + // initialize new tablet | |
| 76 | + tabletProxy->setToolbarMode(_toolbarMode); | |
| 77 | + return tabletProxy; | |
| 70 | 78 | } |
| 71 | 79 | |
| 72 | 80 | void TabletScriptingInterface::setToolbarMode(bool toolbarMode) { |
| 73 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 74 | − | |
| 75 | − _toolbarMode = toolbarMode; | |
| 81 | + { | |
| 82 | + // the only thing guarded should be _toolbarMode | |
| 83 | + // this avoids a deadlock with the Main thread | |
| 84 | + // from Qt::BlockingQueuedEvent invocations later in the call-tree | |
| 85 | + std::lock_guard<std::mutex> guard(_mapMutex); | |
| 86 | + _toolbarMode = toolbarMode; | |
| 87 | + } | |
| 76 | 88 | |
| 77 | 89 | for (auto& iter : _tabletProxies) { |
| 78 | 90 | iter.second->setToolbarMode(toolbarMode); |
| @@ -89,8 +101,9 @@ void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qm · 10 unmodified lines | ||
| 89 | 101 | } |
| 90 | 102 | |
| 91 | 103 | QQuickWindow* TabletScriptingInterface::getTabletWindow() { |
| 92 | − TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet("com.highfidelity.interface.tablet.system")); | |
| 104 | + TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(SYSTEM_TABLET)); | |
| 93 | 105 | QObject* qmlSurface = tablet->getTabletSurface(); |
| 106 | + | |
| 94 | 107 | OffscreenQmlSurface* surface = dynamic_cast<OffscreenQmlSurface*>(qmlSurface); |
| 95 | 108 | |
| 96 | 109 | if (!surface) { |
| @@ -156,7 +169,7 @@ void TabletScriptingInterface::processTabletEvents(QObject* object, const QKeyEv · 59 unmodified lines | ||
| 156 | 169 | |
| 157 | 170 | |
| 158 | 171 | void TabletScriptingInterface::processEvent(const QKeyEvent* event) { |
| 159 | − TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet("com.highfidelity.interface.tablet.system")); | |
| 172 | + TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(SYSTEM_TABLET)); | |
| 160 | 173 | QObject* qmlTablet = tablet->getQmlTablet(); |
| 161 | 174 | QObject* qmlMenu = tablet->getQmlMenu(); |
| 162 | 175 | |
| @@ -185,10 +198,12 @@ class TabletRootWindow : public QmlWindowClass { · 22 unmodified lines | ||
| 185 | 198 | virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; } |
| 186 | 199 | }; |
| 187 | 200 | |
| 188 | −TabletProxy::TabletProxy(QString name) : _name(name) { | |
| 201 | +TabletProxy::TabletProxy(QObject* parent, QString name) : QObject(parent), _name(name) { | |
| 189 | 202 | } |
| 190 | 203 | |
| 191 | 204 | void TabletProxy::setToolbarMode(bool toolbarMode) { |
| 205 | + std::lock_guard<std::mutex> guard(_tabletMutex); | |
| 206 | + | |
| 192 | 207 | if (toolbarMode == _toolbarMode) { |
| 193 | 208 | return; |
| 194 | 209 | } |
| @@ -288,7 +303,7 @@ bool TabletProxy::isPathLoaded(QVariant path) { · 93 unmodified lines | ||
| 288 | 303 | return path.toString() == _currentPathLoaded.toString(); |
| 289 | 304 | } |
| 290 | 305 | void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) { |
| 291 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 306 | + std::lock_guard<std::mutex> guard(_tabletMutex); | |
| 292 | 307 | _qmlOffscreenSurface = qmlOffscreenSurface; |
| 293 | 308 | _qmlTabletRoot = qmlTabletRoot; |
| 294 | 309 | if (_qmlTabletRoot && _qmlOffscreenSurface) { |
| @@ -519,7 +534,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS · 224 unmodified lines | ||
| 519 | 534 | |
| 520 | 535 | QObject* TabletProxy::addButton(const QVariant& properties) { |
| 521 | 536 | auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap())); |
| 522 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 537 | + std::lock_guard<std::mutex> guard(_tabletMutex); | |
| 523 | 538 | _tabletButtonProxies.push_back(tabletButtonProxy); |
| 524 | 539 | if (!_toolbarMode && _qmlTabletRoot) { |
| 525 | 540 | auto tablet = getQmlTablet(); |
| @@ -555,7 +570,7 @@ bool TabletProxy::onHomeScreen() { · 29 unmodified lines | ||
| 555 | 570 | } |
| 556 | 571 | |
| 557 | 572 | void TabletProxy::removeButton(QObject* tabletButtonProxy) { |
| 558 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 573 | + std::lock_guard<std::mutex> guard(_tabletMutex); | |
| 559 | 574 | |
| 560 | 575 | auto tablet = getQmlTablet(); |
| 561 | 576 | if (!tablet) { |
| @@ -743,12 +758,12 @@ TabletButtonProxy::TabletButtonProxy(const QVariantMap& properties) : · 181 unmodified lines | ||
| 743 | 758 | } |
| 744 | 759 | |
| 745 | 760 | void TabletButtonProxy::setQmlButton(QQuickItem* qmlButton) { |
| 746 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 761 | + std::lock_guard<std::mutex> guard(_buttonMutex); | |
| 747 | 762 | _qmlButton = qmlButton; |
| 748 | 763 | } |
| 749 | 764 | |
| 750 | 765 | void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) { |
| 751 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 766 | + std::lock_guard<std::mutex> guard(_buttonMutex); | |
| 752 | 767 | _toolbarButtonProxy = toolbarButtonProxy; |
| 753 | 768 | if (_toolbarButtonProxy) { |
| 754 | 769 | QObject::connect(_toolbarButtonProxy, SIGNAL(clicked()), this, SLOT(clickedSlot())); |
| @@ -756,12 +771,12 @@ void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) { · 1 unmodified line | ||
| 756 | 771 | } |
| 757 | 772 | |
| 758 | 773 | QVariantMap TabletButtonProxy::getProperties() const { |
| 759 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 774 | + std::lock_guard<std::mutex> guard(_buttonMutex); | |
| 760 | 775 | return _properties; |
| 761 | 776 | } |
| 762 | 777 | |
| 763 | 778 | void TabletButtonProxy::editProperties(QVariantMap properties) { |
| 764 | − std::lock_guard<std::mutex> guard(_mutex); | |
| 779 | + std::lock_guard<std::mutex> guard(_buttonMutex); | |
| 765 | 780 | |
| 766 | 781 | QVariantMap::const_iterator iter = properties.constBegin(); |
| 767 | 782 | while (iter != properties.constEnd()) { |