History

merge from upstream

Seth Alves committed 9 years ago

Commit 43f47c12 parents a7e002f 70c985338 files · +1522 −554Browse files

Showing the changes to libraries/script-engine/src/TabletScriptingInterface.cpp (1 of 38 files). Show all

Unified · Split

libraries/script-engine/src/TabletScriptingInterface.cpp+218−49
@@ -11,17 +11,36 @@ · 10 unmodified lines
1111 #include <QtCore/QThread>
1212
1313 #include <AccountManager.h>
14+#include "DependencyManager.h"
1415 #include <PathUtils.h>
16+#include <QmlWindowClass.h>
17+#include <QQmlProperty>
1518 #include <RegisteredMetaTypes.h>
1619 #include "ScriptEngineLogging.h"
17−#include "DependencyManager.h"
18−#include "OffscreenUi.h"
20+#include <OffscreenUi.h>
21+#include <InfoView.h>
1922 #include "SoundEffect.h"
2023
2124 TabletScriptingInterface::TabletScriptingInterface() {
2225 qmlRegisterType<SoundEffect>("Hifi", 1, 0, "SoundEffect");
2326 }
2427
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+
2544 QObject* TabletScriptingInterface::getTablet(const QString& tabletId) {
2645
2746 std::lock_guard<std::mutex> guard(_mutex);
@@ -35,10 +54,21 @@ QObject* TabletScriptingInterface::getTablet(const QString& tabletId) { · 7 unmodified lines
3554 // allocate a new tablet, add it to the map then return it.
3655 auto tabletProxy = QSharedPointer<TabletProxy>(new TabletProxy(tabletId));
3756 _tabletProxies[tabletId] = tabletProxy;
57+ tabletProxy->setToolbarMode(_toolbarMode);
3858 return tabletProxy.data();
3959 }
4060 }
4161
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+
4272 void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) {
4373 TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(tabletId));
4474 if (tablet) {
@@ -141,8 +171,51 @@ static const char* TABLET_SOURCE_URL = "Tablet.qml"; · 96 unmodified lines
141171 static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml";
142172 static const char* VRMENU_SOURCE_URL = "TabletMenu.qml";
143173
174+class TabletRootWindow : public QmlWindowClass {
175+ virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; }
176+};
177+
144178 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+ }
146219 }
147220
148221 static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) {
@@ -195,6 +268,13 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr · 46 unmodified lines
195268 }
196269 });
197270
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+
198278 gotoHomeScreen();
199279
200280 QMetaObject::invokeMethod(_qmlTabletRoot, "setUsername", Q_ARG(const QVariant&, QVariant(getUsername())));
@@ -214,26 +294,42 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr · 13 unmodified lines
214294 }
215295
216296 void TabletProxy::gotoMenuScreen(const QString& submenu) {
217− if (_qmlTabletRoot) {
218− if (_state != State::Menu) {
219− removeButtonsFromHomeScreen();
220− QMetaObject::invokeMethod(_qmlTabletRoot, "setOption", Q_ARG(const QVariant&, QVariant(submenu)));
221− auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
222− QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToMenuScreen()), Qt::DirectConnection);
223− QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL)));
224− _state = State::Menu;
225− emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL));
226− }
297+
298+ QObject* root = nullptr;
299+ if (!_toolbarMode && _qmlTabletRoot) {
300+ root = _qmlTabletRoot;
301+ } else if (_toolbarMode && _desktopWindow) {
302+ root = _desktopWindow->asQuickItem();
303+ }
304+
305+ if (root) {
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)));
227314 }
228315 }
229316
230317 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) {
232327 if (_state != State::QML) {
233328 removeButtonsFromHomeScreen();
234− QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, path));
329+ QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path));
235330 _state = State::QML;
236331 emit screenChanged(QVariant("QML"), path);
332+ QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
237333 }
238334 } else {
239335 qCDebug(scriptengine) << "tablet cannot load QML because _qmlTabletRoot is null";
@@ -267,15 +363,20 @@ void TabletProxy::popFromStack() { · 27 unmodified lines
267363 }
268364
269365 void TabletProxy::gotoHomeScreen() {
270− if (_qmlTabletRoot) {
271− if (_state != State::Home) {
366+ if (_state != State::Home) {
367+ if (!_toolbarMode && _qmlTabletRoot) {
272368 auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
273369 QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()), Qt::DirectConnection);
274370 QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL)));
275371 QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound");
276− _state = State::Home;
277− emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL));
372+ } else if (_toolbarMode && _desktopWindow) {
373+ // close desktop window
374+ if (_desktopWindow->asQuickItem()) {
375+ QMetaObject::invokeMethod(_desktopWindow->asQuickItem(), "setShown", Q_ARG(const QVariant&, QVariant(false)));
376+ }
278377 }
378+ _state = State::Home;
379+ emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL));
279380 }
280381 }
281382
@@ -284,31 +385,52 @@ void TabletProxy::gotoWebScreen(const QString& url) { · 2 unmodified lines
284385 }
285386
286387 void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl) {
287− if (_qmlTabletRoot) {
288− if (_state == State::Home) {
289− removeButtonsFromHomeScreen();
290− }
291− if (_state != State::Web) {
292− QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL)));
293− _state = State::Web;
294− emit screenChanged(QVariant("Web"), QVariant(url));
295− }
296− QMetaObject::invokeMethod(_qmlTabletRoot, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)),
297− Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl)));
388+
389+ QObject* root = nullptr;
390+ if (!_toolbarMode && _qmlTabletRoot) {
391+ root = _qmlTabletRoot;
392+ } else if (_toolbarMode && _desktopWindow) {
393+ root = _desktopWindow->asQuickItem();
394+ }
395+
396+ if (root) {
397+ QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL)));
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)));
298400 }
401+ _state = State::Web;
402+ emit screenChanged(QVariant("Web"), QVariant(url));
299403 }
300404
301405 QObject* TabletProxy::addButton(const QVariant& properties) {
302406 auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
303407 std::lock_guard<std::mutex> guard(_mutex);
304408 _tabletButtonProxies.push_back(tabletButtonProxy);
305− if (_qmlTabletRoot) {
409+ if (!_toolbarMode && _qmlTabletRoot) {
306410 auto tablet = getQmlTablet();
307411 if (tablet) {
308412 addButtonProxyToQmlTablet(tablet, tabletButtonProxy.data());
309413 } else {
310414 qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml";
311415 }
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+ }
312434 }
313435 return tabletButtonProxy.data();
314436 }
@@ -327,11 +449,18 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { · 12 unmodified lines
327449
328450 auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy);
329451 if (iter != _tabletButtonProxies.end()) {
330− if (_qmlTabletRoot) {
452+ if (!_toolbarMode && _qmlTabletRoot) {
331453 (*iter)->setQmlButton(nullptr);
332454 if (tablet) {
333455 QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties()));
334456 }
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);
335464 }
336465 _tabletButtonProxies.erase(iter);
337466 } else {
@@ -358,20 +487,24 @@ void TabletProxy::updateAudioBar(const double micLevel) { · 20 unmodified lines
358487 }
359488
360489 void TabletProxy::emitScriptEvent(QVariant msg) {
361− if (_qmlOffscreenSurface) {
490+ if (!_toolbarMode && _qmlOffscreenSurface) {
362491 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));
363494 }
364495 }
365496
366497 void TabletProxy::sendToQml(QVariant msg) {
367− if (_qmlOffscreenSurface) {
498+ if (!_toolbarMode && _qmlOffscreenSurface) {
368499 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));
369502 }
370503 }
371504
372505 void TabletProxy::addButtonsToHomeScreen() {
373506 auto tablet = getQmlTablet();
374− if (!tablet) {
507+ if (!tablet || _toolbarMode) {
375508 return;
376509 }
377510
@@ -387,30 +520,51 @@ QObject* TabletProxy::getTabletSurface() { · 9 unmodified lines
387520 return _qmlOffscreenSurface;
388521 }
389522
390−void TabletProxy::addButtonsToMenuScreen() {
391− if (!_qmlTabletRoot) {
392− return;
523+void TabletProxy::removeButtonsFromHomeScreen() {
524+ auto tablet = getQmlTablet();
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);
393530 }
531+}
394532
395− auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
396− if (!loader) {
397− return;
533+void TabletProxy::desktopWindowClosed() {
534+ gotoHomeScreen();
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;
398544 }
399545
400− QQuickItem* VrMenu = loader->findChild<QQuickItem*>("tabletMenu");
401− if (VrMenu) {
402− auto offscreenUi = DependencyManager::get<OffscreenUi>();
403− QObject* menu = offscreenUi->getRootMenu();
404− QMetaObject::invokeMethod(VrMenu, "setRootMenu", Qt::AutoConnection, Q_ARG(QVariant, QVariant::fromValue(menu)));
546+ for (auto& buttonProxy : _tabletButtonProxies) {
547+ // copy properties from tablet button proxy to toolbar button proxy.
548+ QObject* toolbarButtonProxy = nullptr;
549+ bool hasResult = QMetaObject::invokeMethod(toolbarProxy, "addButton", connectionType, Q_RETURN_ARG(QObject*, toolbarButtonProxy), Q_ARG(QVariant, buttonProxy->getProperties()));
550+ if (hasResult) {
551+ buttonProxy->setToolbarButtonProxy(toolbarButtonProxy);
552+ } else {
553+ qCWarning(scriptengine) << "ToolbarProxy addButton has no result";
554+ }
405555 }
406556
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)));
408559 }
409560
410−void TabletProxy::removeButtonsFromHomeScreen() {
561+void TabletProxy::removeButtonsFromToolbar() {
411562 auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
563+ QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy();
412564 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);
414568 }
415569 }
416570
@@ -459,12 +613,14 @@ QQuickItem* TabletProxy::getQmlMenu() const { · 42 unmodified lines
459613 //
460614
461615 const QString UUID_KEY = "uuid";
616+const QString OBJECT_NAME_KEY = "objectName";
462617 const QString STABLE_ORDER_KEY = "stableOrder";
463618 static int s_stableOrder = 1;
464619
465620 TabletButtonProxy::TabletButtonProxy(const QVariantMap& properties) : _uuid(QUuid::createUuid()), _stableOrder(++s_stableOrder), _properties(properties) {
466621 // this is used to uniquely identify this button.
467622 _properties[UUID_KEY] = _uuid;
623+ _properties[OBJECT_NAME_KEY] = _uuid.toString();
468624 _properties[STABLE_ORDER_KEY] = _stableOrder;
469625 }
470626
@@ -473,6 +629,14 @@ void TabletButtonProxy::setQmlButton(QQuickItem* qmlButton) { · 2 unmodified lines
473629 _qmlButton = qmlButton;
474630 }
475631
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+
476640 QVariantMap TabletButtonProxy::getProperties() const {
477641 std::lock_guard<std::mutex> guard(_mutex);
478642 return _properties;
@@ -480,6 +644,7 @@ QVariantMap TabletButtonProxy::getProperties() const { · 1 unmodified line
480644
481645 void TabletButtonProxy::editProperties(QVariantMap properties) {
482646 std::lock_guard<std::mutex> guard(_mutex);
647+
483648 QVariantMap::const_iterator iter = properties.constBegin();
484649 while (iter != properties.constEnd()) {
485650 _properties[iter.key()] = iter.value();
@@ -488,6 +653,10 @@ void TabletButtonProxy::editProperties(QVariantMap properties) { · 2 unmodified lines
488653 }
489654 ++iter;
490655 }
656+
657+ if (_toolbarButtonProxy) {
658+ QMetaObject::invokeMethod(_toolbarButtonProxy, "editProperties", Qt::AutoConnection, Q_ARG(QVariantMap, properties));
659+ }
491660 }
492661
493662 #include "TabletScriptingInterface.moc"