Showing the changes to libraries/script-engine/src/TabletScriptingInterface.cpp (1 of 38 files). Show all
Unified · Split
| @@ -11,17 +11,36 @@ · 10 unmodified lines | |||
| 11 | #include <QtCore/QThread> | 11 | #include <QtCore/QThread> |
| 12 | 12 | ||
| 13 | #include <AccountManager.h> | 13 | #include <AccountManager.h> |
| 14 | #include "DependencyManager.h" | ||
| 14 | #include <PathUtils.h> | 15 | #include <PathUtils.h> |
| 16 | #include <QmlWindowClass.h> | ||
| 17 | #include <QQmlProperty> | ||
| 15 | #include <RegisteredMetaTypes.h> | 18 | #include <RegisteredMetaTypes.h> |
| 16 | #include "ScriptEngineLogging.h" | 19 | #include "ScriptEngineLogging.h" |
| 17 | #include "DependencyManager.h" | 20 | #include <OffscreenUi.h> |
| 18 | #include "OffscreenUi.h" | 21 | #include <InfoView.h> |
| 19 | #include "SoundEffect.h" | 22 | #include "SoundEffect.h" |
| 20 | 23 | ||
| 21 | TabletScriptingInterface::TabletScriptingInterface() { | 24 | TabletScriptingInterface::TabletScriptingInterface() { |
| 22 | qmlRegisterType<SoundEffect>("Hifi", 1, 0, "SoundEffect"); | 25 | qmlRegisterType<SoundEffect>("Hifi", 1, 0, "SoundEffect"); |
| 23 | } | 26 | } |
| 24 | 27 | ||
| 28 | QObject* TabletScriptingInterface::getSystemToolbarProxy() { | ||
| 29 | const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; | ||
| 30 | Qt::ConnectionType connectionType = Qt::AutoConnection; | ||
| 31 | if (QThread::currentThread() != _toolbarScriptingInterface->thread()) { | ||
| 32 | connectionType = Qt::BlockingQueuedConnection; | ||
| 33 | } | ||
| 34 | QObject* toolbarProxy = nullptr; | ||
| 35 | bool hasResult = QMetaObject::invokeMethod(_toolbarScriptingInterface, "getToolbar", connectionType, Q_RETURN_ARG(QObject*, toolbarProxy), Q_ARG(QString, SYSTEM_TOOLBAR)); | ||
| 36 | if (hasResult) { | ||
| 37 | return toolbarProxy; | ||
| 38 | } else { | ||
| 39 | qCWarning(scriptengine) << "ToolbarScriptingInterface getToolbar has no result"; | ||
| 40 | return nullptr; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 25 | QObject* TabletScriptingInterface::getTablet(const QString& tabletId) { | 44 | QObject* TabletScriptingInterface::getTablet(const QString& tabletId) { |
| 26 | 45 | ||
| 27 | std::lock_guard<std::mutex> guard(_mutex); | 46 | std::lock_guard<std::mutex> guard(_mutex); |
| @@ -35,10 +54,21 @@ QObject* TabletScriptingInterface::getTablet(const QString& tabletId) { · 7 unmodified lines | |||
| 35 | // allocate a new tablet, add it to the map then return it. | 54 | // allocate a new tablet, add it to the map then return it. |
| 36 | auto tabletProxy = QSharedPointer<TabletProxy>(new TabletProxy(tabletId)); | 55 | auto tabletProxy = QSharedPointer<TabletProxy>(new TabletProxy(tabletId)); |
| 37 | _tabletProxies[tabletId] = tabletProxy; | 56 | _tabletProxies[tabletId] = tabletProxy; |
| 57 | tabletProxy->setToolbarMode(_toolbarMode); | ||
| 38 | return tabletProxy.data(); | 58 | return tabletProxy.data(); |
| 39 | } | 59 | } |
| 40 | } | 60 | } |
| 41 | 61 | ||
| 62 | void TabletScriptingInterface::setToolbarMode(bool toolbarMode) { | ||
| 63 | std::lock_guard<std::mutex> guard(_mutex); | ||
| 64 | |||
| 65 | _toolbarMode = toolbarMode; | ||
| 66 | |||
| 67 | for (auto& iter : _tabletProxies) { | ||
| 68 | iter.second->setToolbarMode(toolbarMode); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 42 | void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) { | 72 | void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) { |
| 43 | TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(tabletId)); | 73 | TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(tabletId)); |
| 44 | if (tablet) { | 74 | if (tablet) { |
| @@ -141,8 +171,51 @@ static const char* TABLET_SOURCE_URL = "Tablet.qml"; · 96 unmodified lines | |||
| 141 | static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml"; | 171 | static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml"; |
| 142 | static const char* VRMENU_SOURCE_URL = "TabletMenu.qml"; | 172 | static const char* VRMENU_SOURCE_URL = "TabletMenu.qml"; |
| 143 | 173 | ||
| 174 | class TabletRootWindow : public QmlWindowClass { | ||
| 175 | virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; } | ||
| 176 | }; | ||
| 177 | |||
| 144 | TabletProxy::TabletProxy(QString name) : _name(name) { | 178 | TabletProxy::TabletProxy(QString name) : _name(name) { |
| 145 | ; | 179 | |
| 180 | } | ||
| 181 | |||
| 182 | void TabletProxy::setToolbarMode(bool toolbarMode) { | ||
| 183 | if (toolbarMode == _toolbarMode) { | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | _toolbarMode = toolbarMode; | ||
| 188 | |||
| 189 | if (toolbarMode) { | ||
| 190 | removeButtonsFromHomeScreen(); | ||
| 191 | addButtonsToToolbar(); | ||
| 192 | |||
| 193 | // create new desktop window | ||
| 194 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); | ||
| 195 | offscreenUi->executeOnUiThread([=] { | ||
| 196 | auto tabletRootWindow = new TabletRootWindow(); | ||
| 197 | tabletRootWindow->initQml(QVariantMap()); | ||
| 198 | auto quickItem = tabletRootWindow->asQuickItem(); | ||
| 199 | _desktopWindow = tabletRootWindow; | ||
| 200 | QMetaObject::invokeMethod(quickItem, "setShown", Q_ARG(const QVariant&, QVariant(false))); | ||
| 201 | |||
| 202 | QObject::connect(quickItem, SIGNAL(windowClosed()), this, SLOT(desktopWindowClosed())); | ||
| 203 | |||
| 204 | QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SIGNAL(webEventReceived(QVariant))); | ||
| 205 | |||
| 206 | // forward qml surface events to interface js | ||
| 207 | connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); | ||
| 208 | }); | ||
| 209 | } else { | ||
| 210 | removeButtonsFromToolbar(); | ||
| 211 | addButtonsToHomeScreen(); | ||
| 212 | |||
| 213 | // destroy desktop window | ||
| 214 | if (_desktopWindow) { | ||
| 215 | _desktopWindow->deleteLater(); | ||
| 216 | _desktopWindow = nullptr; | ||
| 217 | } | ||
| 218 | } | ||
| 146 | } | 219 | } |
| 147 | 220 | ||
| 148 | static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) { | 221 | static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) { |
| @@ -195,6 +268,13 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr · 46 unmodified lines | |||
| 195 | } | 268 | } |
| 196 | }); | 269 | }); |
| 197 | 270 | ||
| 271 | if (_toolbarMode) { | ||
| 272 | // if someone creates the tablet in toolbar mode, make sure to display the home screen on the tablet. | ||
| 273 | auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader"); | ||
| 274 | QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()), Qt::DirectConnection); | ||
| 275 | QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); | ||
| 276 | } | ||
| 277 | |||
| 198 | gotoHomeScreen(); | 278 | gotoHomeScreen(); |
| 199 | 279 | ||
| 200 | QMetaObject::invokeMethod(_qmlTabletRoot, "setUsername", Q_ARG(const QVariant&, QVariant(getUsername()))); | 280 | QMetaObject::invokeMethod(_qmlTabletRoot, "setUsername", Q_ARG(const QVariant&, QVariant(getUsername()))); |
| @@ -214,26 +294,42 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr · 13 unmodified lines | |||
| 214 | } | 294 | } |
| 215 | 295 | ||
| 216 | void TabletProxy::gotoMenuScreen(const QString& submenu) { | 296 | void TabletProxy::gotoMenuScreen(const QString& submenu) { |
| 217 | if (_qmlTabletRoot) { | 297 | |
| 218 | if (_state != State::Menu) { | 298 | QObject* root = nullptr; |
| 219 | removeButtonsFromHomeScreen(); | 299 | if (!_toolbarMode && _qmlTabletRoot) { |
| 220 | QMetaObject::invokeMethod(_qmlTabletRoot, "setOption", Q_ARG(const QVariant&, QVariant(submenu))); | 300 | root = _qmlTabletRoot; |
| 221 | auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader"); | 301 | } else if (_toolbarMode && _desktopWindow) { |
| 222 | QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToMenuScreen()), Qt::DirectConnection); | 302 | root = _desktopWindow->asQuickItem(); |
| 223 | QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL))); | 303 | } |
| 224 | _state = State::Menu; | 304 | |
| 225 | emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL)); | 305 | if (root) { |
| 226 | } | 306 | removeButtonsFromHomeScreen(); |
| 307 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); | ||
| 308 | QObject* menu = offscreenUi->getRootMenu(); | ||
| 309 | QMetaObject::invokeMethod(root, "setMenuProperties", Q_ARG(QVariant, QVariant::fromValue(menu)), Q_ARG(const QVariant&, QVariant(submenu))); | ||
| 310 | QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL))); | ||
| 311 | _state = State::Menu; | ||
| 312 | emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL)); | ||
| 313 | QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); | ||
| 227 | } | 314 | } |
| 228 | } | 315 | } |
| 229 | 316 | ||
| 230 | void TabletProxy::loadQMLSource(const QVariant& path) { | 317 | void TabletProxy::loadQMLSource(const QVariant& path) { |
| 231 | if (_qmlTabletRoot) { | 318 | |
| 319 | QObject* root = nullptr; | ||
| 320 | if (!_toolbarMode && _qmlTabletRoot) { | ||
| 321 | root = _qmlTabletRoot; | ||
| 322 | } else if (_toolbarMode && _desktopWindow) { | ||
| 323 | root = _desktopWindow->asQuickItem(); | ||
| 324 | } | ||
| 325 | |||
| 326 | if (root) { | ||
| 232 | if (_state != State::QML) { | 327 | if (_state != State::QML) { |
| 233 | removeButtonsFromHomeScreen(); | 328 | removeButtonsFromHomeScreen(); |
| 234 | QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, path)); | 329 | QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path)); |
| 235 | _state = State::QML; | 330 | _state = State::QML; |
| 236 | emit screenChanged(QVariant("QML"), path); | 331 | emit screenChanged(QVariant("QML"), path); |
| 332 | QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); | ||
| 237 | } | 333 | } |
| 238 | } else { | 334 | } else { |
| 239 | qCDebug(scriptengine) << "tablet cannot load QML because _qmlTabletRoot is null"; | 335 | qCDebug(scriptengine) << "tablet cannot load QML because _qmlTabletRoot is null"; |
| @@ -267,15 +363,20 @@ void TabletProxy::popFromStack() { · 27 unmodified lines | |||
| 267 | } | 363 | } |
| 268 | 364 | ||
| 269 | void TabletProxy::gotoHomeScreen() { | 365 | void TabletProxy::gotoHomeScreen() { |
| 270 | if (_qmlTabletRoot) { | 366 | if (_state != State::Home) { |
| 271 | if (_state != State::Home) { | 367 | if (!_toolbarMode && _qmlTabletRoot) { |
| 272 | auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader"); | 368 | auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader"); |
| 273 | QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()), Qt::DirectConnection); | 369 | QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()), Qt::DirectConnection); |
| 274 | QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); | 370 | QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL))); |
| 275 | QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound"); | 371 | QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound"); |
| 276 | _state = State::Home; | 372 | } else if (_toolbarMode && _desktopWindow) { |
| 277 | emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL)); | 373 | // close desktop window |
| 374 | if (_desktopWindow->asQuickItem()) { | ||
| 375 | QMetaObject::invokeMethod(_desktopWindow->asQuickItem(), "setShown", Q_ARG(const QVariant&, QVariant(false))); | ||
| 376 | } | ||
| 278 | } | 377 | } |
| 378 | _state = State::Home; | ||
| 379 | emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL)); | ||
| 279 | } | 380 | } |
| 280 | } | 381 | } |
| 281 | 382 | ||
| @@ -284,31 +385,52 @@ void TabletProxy::gotoWebScreen(const QString& url) { · 2 unmodified lines | |||
| 284 | } | 385 | } |
| 285 | 386 | ||
| 286 | void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl) { | 387 | void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl) { |
| 287 | if (_qmlTabletRoot) { | 388 | |
| 288 | if (_state == State::Home) { | 389 | QObject* root = nullptr; |
| 289 | removeButtonsFromHomeScreen(); | 390 | if (!_toolbarMode && _qmlTabletRoot) { |
| 290 | } | 391 | root = _qmlTabletRoot; |
| 291 | if (_state != State::Web) { | 392 | } else if (_toolbarMode && _desktopWindow) { |
| 292 | QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL))); | 393 | root = _desktopWindow->asQuickItem(); |
| 293 | _state = State::Web; | 394 | } |
| 294 | emit screenChanged(QVariant("Web"), QVariant(url)); | 395 | |
| 295 | } | 396 | if (root) { |
| 296 | QMetaObject::invokeMethod(_qmlTabletRoot, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), | 397 | QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL))); |
| 297 | Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); | 398 | QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); |
| 399 | QMetaObject::invokeMethod(root, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); | ||
| 298 | } | 400 | } |
| 401 | _state = State::Web; | ||
| 402 | emit screenChanged(QVariant("Web"), QVariant(url)); | ||
| 299 | } | 403 | } |
| 300 | 404 | ||
| 301 | QObject* TabletProxy::addButton(const QVariant& properties) { | 405 | QObject* TabletProxy::addButton(const QVariant& properties) { |
| 302 | auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap())); | 406 | auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap())); |
| 303 | std::lock_guard<std::mutex> guard(_mutex); | 407 | std::lock_guard<std::mutex> guard(_mutex); |
| 304 | _tabletButtonProxies.push_back(tabletButtonProxy); | 408 | _tabletButtonProxies.push_back(tabletButtonProxy); |
| 305 | if (_qmlTabletRoot) { | 409 | if (!_toolbarMode && _qmlTabletRoot) { |
| 306 | auto tablet = getQmlTablet(); | 410 | auto tablet = getQmlTablet(); |
| 307 | if (tablet) { | 411 | if (tablet) { |
| 308 | addButtonProxyToQmlTablet(tablet, tabletButtonProxy.data()); | 412 | addButtonProxyToQmlTablet(tablet, tabletButtonProxy.data()); |
| 309 | } else { | 413 | } else { |
| 310 | qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; | 414 | qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; |
| 311 | } | 415 | } |
| 416 | } else if (_toolbarMode) { | ||
| 417 | |||
| 418 | auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); | ||
| 419 | QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy(); | ||
| 420 | |||
| 421 | Qt::ConnectionType connectionType = Qt::AutoConnection; | ||
| 422 | if (QThread::currentThread() != toolbarProxy->thread()) { | ||
| 423 | connectionType = Qt::BlockingQueuedConnection; | ||
| 424 | } | ||
| 425 | |||
| 426 | // copy properties from tablet button proxy to toolbar button proxy. | ||
| 427 | QObject* toolbarButtonProxy = nullptr; | ||
| 428 | bool hasResult = QMetaObject::invokeMethod(toolbarProxy, "addButton", connectionType, Q_RETURN_ARG(QObject*, toolbarButtonProxy), Q_ARG(QVariant, tabletButtonProxy->getProperties())); | ||
| 429 | if (hasResult) { | ||
| 430 | tabletButtonProxy->setToolbarButtonProxy(toolbarButtonProxy); | ||
| 431 | } else { | ||
| 432 | qCWarning(scriptengine) << "ToolbarProxy addButton has no result"; | ||
| 433 | } | ||
| 312 | } | 434 | } |
| 313 | return tabletButtonProxy.data(); | 435 | return tabletButtonProxy.data(); |
| 314 | } | 436 | } |
| @@ -327,11 +449,18 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { · 12 unmodified lines | |||
| 327 | 449 | ||
| 328 | auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); | 450 | auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); |
| 329 | if (iter != _tabletButtonProxies.end()) { | 451 | if (iter != _tabletButtonProxies.end()) { |
| 330 | if (_qmlTabletRoot) { | 452 | if (!_toolbarMode && _qmlTabletRoot) { |
| 331 | (*iter)->setQmlButton(nullptr); | 453 | (*iter)->setQmlButton(nullptr); |
| 332 | if (tablet) { | 454 | if (tablet) { |
| 333 | QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); | 455 | QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); |
| 334 | } | 456 | } |
| 457 | } else if (_toolbarMode) { | ||
| 458 | auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); | ||
| 459 | QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy(); | ||
| 460 | |||
| 461 | // remove button from toolbarProxy | ||
| 462 | QMetaObject::invokeMethod(toolbarProxy, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getUuid().toString())); | ||
| 463 | (*iter)->setToolbarButtonProxy(nullptr); | ||
| 335 | } | 464 | } |
| 336 | _tabletButtonProxies.erase(iter); | 465 | _tabletButtonProxies.erase(iter); |
| 337 | } else { | 466 | } else { |
| @@ -358,20 +487,24 @@ void TabletProxy::updateAudioBar(const double micLevel) { · 20 unmodified lines | |||
| 358 | } | 487 | } |
| 359 | 488 | ||
| 360 | void TabletProxy::emitScriptEvent(QVariant msg) { | 489 | void TabletProxy::emitScriptEvent(QVariant msg) { |
| 361 | if (_qmlOffscreenSurface) { | 490 | if (!_toolbarMode && _qmlOffscreenSurface) { |
| 362 | QMetaObject::invokeMethod(_qmlOffscreenSurface, "emitScriptEvent", Qt::AutoConnection, Q_ARG(QVariant, msg)); | 491 | QMetaObject::invokeMethod(_qmlOffscreenSurface, "emitScriptEvent", Qt::AutoConnection, Q_ARG(QVariant, msg)); |
| 492 | } else if (_toolbarMode && _desktopWindow) { | ||
| 493 | QMetaObject::invokeMethod(_desktopWindow, "emitScriptEvent", Qt::AutoConnection, Q_ARG(QVariant, msg)); | ||
| 363 | } | 494 | } |
| 364 | } | 495 | } |
| 365 | 496 | ||
| 366 | void TabletProxy::sendToQml(QVariant msg) { | 497 | void TabletProxy::sendToQml(QVariant msg) { |
| 367 | if (_qmlOffscreenSurface) { | 498 | if (!_toolbarMode && _qmlOffscreenSurface) { |
| 368 | QMetaObject::invokeMethod(_qmlOffscreenSurface, "sendToQml", Qt::AutoConnection, Q_ARG(QVariant, msg)); | 499 | QMetaObject::invokeMethod(_qmlOffscreenSurface, "sendToQml", Qt::AutoConnection, Q_ARG(QVariant, msg)); |
| 500 | } else if (_toolbarMode && _desktopWindow) { | ||
| 501 | QMetaObject::invokeMethod(_desktopWindow, "sendToQml", Qt::AutoConnection, Q_ARG(QVariant, msg)); | ||
| 369 | } | 502 | } |
| 370 | } | 503 | } |
| 371 | 504 | ||
| 372 | void TabletProxy::addButtonsToHomeScreen() { | 505 | void TabletProxy::addButtonsToHomeScreen() { |
| 373 | auto tablet = getQmlTablet(); | 506 | auto tablet = getQmlTablet(); |
| 374 | if (!tablet) { | 507 | if (!tablet || _toolbarMode) { |
| 375 | return; | 508 | return; |
| 376 | } | 509 | } |
| 377 | 510 | ||
| @@ -387,30 +520,51 @@ QObject* TabletProxy::getTabletSurface() { · 9 unmodified lines | |||
| 387 | return _qmlOffscreenSurface; | 520 | return _qmlOffscreenSurface; |
| 388 | } | 521 | } |
| 389 | 522 | ||
| 390 | void TabletProxy::addButtonsToMenuScreen() { | 523 | void TabletProxy::removeButtonsFromHomeScreen() { |
| 391 | if (!_qmlTabletRoot) { | 524 | auto tablet = getQmlTablet(); |
| 392 | return; | 525 | for (auto& buttonProxy : _tabletButtonProxies) { |
| 526 | if (tablet) { | ||
| 527 | QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getProperties())); | ||
| 528 | } | ||
| 529 | buttonProxy->setQmlButton(nullptr); | ||
| 393 | } | 530 | } |
| 531 | } | ||
| 394 | 532 | ||
| 395 | auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader"); | 533 | void TabletProxy::desktopWindowClosed() { |
| 396 | if (!loader) { | 534 | gotoHomeScreen(); |
| 397 | return; | 535 | } |
| 536 | |||
| 537 | void TabletProxy::addButtonsToToolbar() { | ||
| 538 | auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); | ||
| 539 | QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy(); | ||
| 540 | |||
| 541 | Qt::ConnectionType connectionType = Qt::AutoConnection; | ||
| 542 | if (QThread::currentThread() != toolbarProxy->thread()) { | ||
| 543 | connectionType = Qt::BlockingQueuedConnection; | ||
| 398 | } | 544 | } |
| 399 | 545 | ||
| 400 | QQuickItem* VrMenu = loader->findChild<QQuickItem*>("tabletMenu"); | 546 | for (auto& buttonProxy : _tabletButtonProxies) { |
| 401 | if (VrMenu) { | 547 | // copy properties from tablet button proxy to toolbar button proxy. |
| 402 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); | 548 | QObject* toolbarButtonProxy = nullptr; |
| 403 | QObject* menu = offscreenUi->getRootMenu(); | 549 | bool hasResult = QMetaObject::invokeMethod(toolbarProxy, "addButton", connectionType, Q_RETURN_ARG(QObject*, toolbarButtonProxy), Q_ARG(QVariant, buttonProxy->getProperties())); |
| 404 | QMetaObject::invokeMethod(VrMenu, "setRootMenu", Qt::AutoConnection, Q_ARG(QVariant, QVariant::fromValue(menu))); | 550 | if (hasResult) { |
| 551 | buttonProxy->setToolbarButtonProxy(toolbarButtonProxy); | ||
| 552 | } else { | ||
| 553 | qCWarning(scriptengine) << "ToolbarProxy addButton has no result"; | ||
| 554 | } | ||
| 405 | } | 555 | } |
| 406 | 556 | ||
| 407 | QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToMenuScreen())); | 557 | // make the toolbar visible |
| 558 | QMetaObject::invokeMethod(toolbarProxy, "writeProperty", Qt::AutoConnection, Q_ARG(QString, "visible"), Q_ARG(QVariant, QVariant(true))); | ||
| 408 | } | 559 | } |
| 409 | 560 | ||
| 410 | void TabletProxy::removeButtonsFromHomeScreen() { | 561 | void TabletProxy::removeButtonsFromToolbar() { |
| 411 | auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); | 562 | auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); |
| 563 | QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy(); | ||
| 412 | for (auto& buttonProxy : _tabletButtonProxies) { | 564 | for (auto& buttonProxy : _tabletButtonProxies) { |
| 413 | buttonProxy->setQmlButton(nullptr); | 565 | // remove button from toolbarProxy |
| 566 | QMetaObject::invokeMethod(toolbarProxy, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getUuid().toString())); | ||
| 567 | buttonProxy->setToolbarButtonProxy(nullptr); | ||
| 414 | } | 568 | } |
| 415 | } | 569 | } |
| 416 | 570 | ||
| @@ -459,12 +613,14 @@ QQuickItem* TabletProxy::getQmlMenu() const { · 42 unmodified lines | |||
| 459 | // | 613 | // |
| 460 | 614 | ||
| 461 | const QString UUID_KEY = "uuid"; | 615 | const QString UUID_KEY = "uuid"; |
| 616 | const QString OBJECT_NAME_KEY = "objectName"; | ||
| 462 | const QString STABLE_ORDER_KEY = "stableOrder"; | 617 | const QString STABLE_ORDER_KEY = "stableOrder"; |
| 463 | static int s_stableOrder = 1; | 618 | static int s_stableOrder = 1; |
| 464 | 619 | ||
| 465 | TabletButtonProxy::TabletButtonProxy(const QVariantMap& properties) : _uuid(QUuid::createUuid()), _stableOrder(++s_stableOrder), _properties(properties) { | 620 | TabletButtonProxy::TabletButtonProxy(const QVariantMap& properties) : _uuid(QUuid::createUuid()), _stableOrder(++s_stableOrder), _properties(properties) { |
| 466 | // this is used to uniquely identify this button. | 621 | // this is used to uniquely identify this button. |
| 467 | _properties[UUID_KEY] = _uuid; | 622 | _properties[UUID_KEY] = _uuid; |
| 623 | _properties[OBJECT_NAME_KEY] = _uuid.toString(); | ||
| 468 | _properties[STABLE_ORDER_KEY] = _stableOrder; | 624 | _properties[STABLE_ORDER_KEY] = _stableOrder; |
| 469 | } | 625 | } |
| 470 | 626 | ||
| @@ -473,6 +629,14 @@ void TabletButtonProxy::setQmlButton(QQuickItem* qmlButton) { · 2 unmodified lines | |||
| 473 | _qmlButton = qmlButton; | 629 | _qmlButton = qmlButton; |
| 474 | } | 630 | } |
| 475 | 631 | ||
| 632 | void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) { | ||
| 633 | std::lock_guard<std::mutex> guard(_mutex); | ||
| 634 | _toolbarButtonProxy = toolbarButtonProxy; | ||
| 635 | if (_toolbarButtonProxy) { | ||
| 636 | QObject::connect(_toolbarButtonProxy, SIGNAL(clicked()), this, SLOT(clickedSlot())); | ||
| 637 | } | ||
| 638 | } | ||
| 639 | |||
| 476 | QVariantMap TabletButtonProxy::getProperties() const { | 640 | QVariantMap TabletButtonProxy::getProperties() const { |
| 477 | std::lock_guard<std::mutex> guard(_mutex); | 641 | std::lock_guard<std::mutex> guard(_mutex); |
| 478 | return _properties; | 642 | return _properties; |
| @@ -480,6 +644,7 @@ QVariantMap TabletButtonProxy::getProperties() const { · 1 unmodified line | |||
| 480 | 644 | ||
| 481 | void TabletButtonProxy::editProperties(QVariantMap properties) { | 645 | void TabletButtonProxy::editProperties(QVariantMap properties) { |
| 482 | std::lock_guard<std::mutex> guard(_mutex); | 646 | std::lock_guard<std::mutex> guard(_mutex); |
| 647 | |||
| 483 | QVariantMap::const_iterator iter = properties.constBegin(); | 648 | QVariantMap::const_iterator iter = properties.constBegin(); |
| 484 | while (iter != properties.constEnd()) { | 649 | while (iter != properties.constEnd()) { |
| 485 | _properties[iter.key()] = iter.value(); | 650 | _properties[iter.key()] = iter.value(); |
| @@ -488,6 +653,10 @@ void TabletButtonProxy::editProperties(QVariantMap properties) { · 2 unmodified lines | |||
| 488 | } | 653 | } |
| 489 | ++iter; | 654 | ++iter; |
| 490 | } | 655 | } |
| 656 | |||
| 657 | if (_toolbarButtonProxy) { | ||
| 658 | QMetaObject::invokeMethod(_toolbarButtonProxy, "editProperties", Qt::AutoConnection, Q_ARG(QVariantMap, properties)); | ||
| 659 | } | ||
| 491 | } | 660 | } |
| 492 | 661 | ||
| 493 | #include "TabletScriptingInterface.moc" | 662 | #include "TabletScriptingInterface.moc" |