diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/HelpApp.qml b/interface/resources/qml/hifi/simplifiedUI/helpApp/HelpApp.qml
new file mode 100644
index 0000000000..59d0caf30a
--- /dev/null
+++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/HelpApp.qml
@@ -0,0 +1,154 @@
+//
+// HelpApp.qml
+//
+// Created by Zach Fox on 2019-08-07
+// Copyright 2019 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import "../simplifiedConstants" as SimplifiedConstants
+import "../simplifiedControls" as SimplifiedControls
+import stylesUit 1.0 as HifiStylesUit
+import "./controls" as HelpControls
+import "./about" as HelpAbout
+
+Rectangle {
+ property string activeTabView: "controlsTabView"
+ id: root
+ color: simplifiedUI.colors.darkBackground
+ anchors.fill: parent
+
+ SimplifiedConstants.SimplifiedConstants {
+ id: simplifiedUI
+ }
+
+ focus: true
+
+ Component.onCompleted: {
+ root.forceActiveFocus();
+ }
+
+
+ Rectangle {
+ id: tabContainer
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 64
+ color: simplifiedUI.colors.highlightOnDark
+
+ ListModel {
+ id: tabListModel
+
+ ListElement {
+ tabTitle: "Controls"
+ tabViewName: "controlsTabView"
+ }
+ ListElement {
+ tabTitle: "About"
+ tabViewName: "aboutTabView"
+ }
+ }
+
+
+ Component {
+ id: highlightBar
+ Rectangle {
+ width: tabListView.currentItem.width
+ height: tabListView.currentItem.height
+ color: simplifiedUI.colors.darkBackground
+ x: tabListView.currentItem.x
+ Behavior on x {
+ SmoothedAnimation {
+ duration: 250
+ }
+ }
+ Behavior on width {
+ SmoothedAnimation {
+ duration: 250
+ }
+ }
+ }
+ }
+
+
+ ListView {
+ id: tabListView
+ anchors.fill: parent
+ contentHeight: parent.height
+ contentWidth: childrenRect.width
+ orientation: ListView.Horizontal
+ model: tabListModel
+ highlight: highlightBar
+ highlightFollowsCurrentItem: false
+ interactive: contentItem.width > width
+ delegate: Item {
+ width: tabTitleText.paintedWidth + 32
+ height: parent.height
+
+ HifiStylesUit.GraphikRegular {
+ id: tabTitleText
+ color: simplifiedUI.colors.text.white
+ anchors.fill: parent
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ text: model.tabTitle
+ size: 24
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ tabListView.currentIndex = index;
+ root.activeTabView = model.tabViewName;
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ id: tabViewContainers
+ anchors.top: tabContainer.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+
+
+ HelpControls.HelpControls {
+ id: controlsTabViewContainer
+ visible: activeTabView === "controlsTabView"
+ anchors.fill: parent
+ }
+
+ HelpAbout.HelpAbout {
+ id: aboutTabViewContainer
+ visible: activeTabView === "aboutTabView"
+ anchors.fill: parent
+ }
+
+ SimplifiedControls.VerticalScrollBar {
+ parent: {
+ if (activeTabView === "generalTabView") {
+ controlsTabViewContainers
+ } else if (activeTabView === "aboutTabView") {
+ aboutTabViewContainer
+ }
+ }
+ }
+ }
+
+
+ function fromScript(message) {
+ switch (message.method) {
+ default:
+ console.log('HelpApp.qml: Unrecognized message from JS');
+ break;
+ }
+ }
+ signal sendToScript(var message);
+}
diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml b/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml
new file mode 100644
index 0000000000..25f1a14a6a
--- /dev/null
+++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml
@@ -0,0 +1,359 @@
+//
+// HelpAbout.qml
+//
+// Created by Zach Fox on 2019-08-07
+// Copyright 2019 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import "../../simplifiedConstants" as SimplifiedConstants
+import "../../simplifiedControls" as SimplifiedControls
+import stylesUit 1.0 as HifiStylesUit
+import QtQuick.Layouts 1.3
+
+Flickable {
+ id: root
+ contentWidth: parent.width
+ contentHeight: aboutColumnLayout.height
+ clip: true
+
+ onVisibleChanged: {
+ if (visible) {
+ root.contentX = 0;
+ root.contentY = 0;
+
+ // When the user clicks the About tab, refresh the audio I/O model so that
+ // the delegate Component.onCompleted handlers fire, which will update
+ // the text that appears in the About screen.
+ audioOutputDevices.model = undefined;
+ audioOutputDevices.model = AudioScriptingInterface.devices.output;
+ audioInputDevices.model = undefined;
+ audioInputDevices.model = AudioScriptingInterface.devices.input;
+ }
+ }
+
+
+ SimplifiedConstants.SimplifiedConstants {
+ id: simplifiedUI
+ }
+
+
+ Image {
+ id: accent
+ source: "../images/accent3.svg"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ width: 83
+ height: 156
+ transform: Scale {
+ xScale: -1
+ origin.x: accent.width / 2
+ origin.y: accent.height / 2
+ }
+ }
+
+
+ ColumnLayout {
+ id: aboutColumnLayout
+ anchors.left: parent.left
+ anchors.leftMargin: 26
+ anchors.right: parent.right
+ anchors.rightMargin: 26
+ anchors.top: parent.top
+ spacing: 0
+
+ ColumnLayout {
+ id: platformInfoContainer
+ Layout.preferredWidth: parent.width
+ Layout.bottomMargin: 24
+ spacing: 0
+
+ HifiStylesUit.GraphikSemiBold {
+ text: "About Your Configuration"
+ Layout.maximumWidth: parent.width
+ Layout.topMargin: 16
+ Layout.bottomMargin: 8
+ height: paintedHeight
+ size: 22
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "Use the button below to get a copy to share with us."
+ Layout.maximumWidth: parent.width
+ Layout.bottomMargin: 8
+ height: paintedHeight
+ size: 18
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "Version " + Window.checkVersion()
+ Layout.maximumWidth: parent.width
+ Layout.topMargin: 8
+ Layout.bottomMargin: 8
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikSemiBold {
+ text: "Platform Info"
+ Layout.maximumWidth: parent.width
+ Layout.topMargin: 8
+ Layout.bottomMargin: 8
+ height: paintedHeight
+ size: 22
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "Computer Vendor/Model:"
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+
+ Component.onCompleted: {
+ var computer = JSON.parse(PlatformInfo.getComputer());
+ var computerVendor = computer.vendor;
+ if (computerVendor.length === 0) {
+ computerVendor = "Unknown";
+ }
+ var computerModel = computer.model;
+ if (computerModel.length === 0) {
+ computerModel = "Unknown";
+ }
+
+ text = "Computer Vendor/Model: " + computerVendor + "/" + computerModel;
+ }
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "Profiled Platform Tier: " + PlatformInfo.getTierProfiled()
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "OS Type: " + PlatformInfo.getOperatingSystemType()
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "CPU:"
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+
+ Component.onCompleted: {
+ var cpu = JSON.parse(PlatformInfo.getCPU(0));
+ var cpuModel = cpu.model;
+ if (cpuModel.length === 0) {
+ cpuModel = "Unknown";
+ }
+
+ text = "CPU: " + cpuModel;
+ }
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "# CPUs: " + PlatformInfo.getNumCPUs()
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "# CPU Cores: " + PlatformInfo.getNumLogicalCores()
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB"
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "GPU: "
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+
+ Component.onCompleted: {
+ var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU()));
+ var gpuModel = gpu.model;
+ if (gpuModel.length === 0) {
+ gpuModel = "Unknown";
+ }
+
+ text = "GPU: " + gpuModel;
+ }
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None"))
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ // This is a bit of a hack to get the name of the currently-selected audio input device
+ // in the current mode (Desktop or VR). The reason this is necessary is because it seems to me like
+ // the only way one can get a human-readable list of the audio I/O devices is by using a ListView
+ // and grabbing the names from the AudioScriptingInterface; you can't do it using a ListModel.
+ // See `AudioDevices.h`, specifically the comment above the declaration of `QVariant data()`.
+ ListView {
+ id: audioInputDevices
+ visible: false
+ property string selectedInputDeviceName
+ Layout.preferredWidth: parent.width
+ Layout.preferredHeight: contentItem.height
+ interactive: false
+ delegate: Item {
+ Component.onCompleted: {
+ if (HMD.active && selectedHMD) {
+ audioInputDevices.selectedInputDeviceName = model.devicename
+ } else if (!HMD.active && selectedDesktop) {
+ audioInputDevices.selectedInputDeviceName = model.devicename
+ }
+ }
+ }
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "Audio Input: " + audioInputDevices.selectedInputDeviceName
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+
+ // This is a bit of a hack to get the name of the currently-selected audio output device
+ // in the current mode (Desktop or VR). The reason this is necessary is because it seems to me like
+ // the only way one can get a human-readable list of the audio I/O devices is by using a ListView
+ // and grabbing the names from the AudioScriptingInterface; you can't do it using a ListModel.
+ // See `AudioDevices.h`, specifically the comment above the declaration of `QVariant data()`.
+ ListView {
+ id: audioOutputDevices
+ visible: false
+ property string selectedOutputDeviceName
+ Layout.preferredWidth: parent.width
+ Layout.preferredHeight: contentItem.height
+ interactive: false
+ delegate: Item {
+ Component.onCompleted: {
+ if (HMD.active && selectedHMD) {
+ audioOutputDevices.selectedOutputDeviceName = model.devicename
+ } else if (!HMD.active && selectedDesktop) {
+ audioOutputDevices.selectedOutputDeviceName = model.devicename
+ }
+ }
+ }
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "Audio Output: " + audioOutputDevices.selectedOutputDeviceName
+ Layout.maximumWidth: parent.width
+ height: paintedHeight
+ size: 16
+ color: simplifiedUI.colors.text.white
+ wrapMode: Text.Wrap
+ }
+
+ SimplifiedControls.Button {
+ Layout.topMargin: 8
+ width: 200
+ height: 32
+ text: "Copy to Clipboard"
+ temporaryText: "Copied!"
+
+ onClicked: {
+ Window.copyToClipboard(root.buildPlatformInfoTextToCopy());
+ showTemporaryText();
+ }
+ }
+ }
+ }
+
+ function buildPlatformInfoTextToCopy() {
+ var textToCopy = "**About Interface**\n";
+ textToCopy += "Interface Version: " + Window.checkVersion() + "\n";
+ textToCopy += "\n**Platform Info**\n";
+
+ var computer = JSON.parse(PlatformInfo.getComputer());
+ var computerVendor = computer.vendor;
+ if (computerVendor.length === 0) {
+ computerVendor = "Unknown";
+ }
+ var computerModel = computer.model;
+ if (computerModel.length === 0) {
+ computerModel = "Unknown";
+ }
+
+ textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n";
+ textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n";
+ textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n";
+
+ var cpu = JSON.parse(PlatformInfo.getCPU(0));
+ var cpuModel = cpu.model;
+ if (cpuModel.length === 0) {
+ cpuModel = "Unknown";
+ }
+
+ textToCopy += "CPU: " + cpuModel + "\n";
+ textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n";
+ textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n";
+ textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n";
+
+ var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU()));
+ var gpuModel = gpu.model;
+ if (gpuModel.length === 0) {
+ gpuModel = "Unknown";
+ }
+
+ textToCopy += "GPU: " + gpuModel + "\n";
+ textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + "\n";
+ textToCopy += "Audio Input: " + audioInputDevices.selectedInputDeviceName + "\n";
+ textToCopy += "Audio Output: " + audioOutputDevices.selectedOutputDeviceName + "\n";
+
+ textToCopy += "\n**All Platform Info**\n";
+ textToCopy += JSON.stringify(JSON.parse(PlatformInfo.getPlatform()), null, 4);
+
+ return textToCopy;
+ }
+}
diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/controls/HelpControls.qml b/interface/resources/qml/hifi/simplifiedUI/helpApp/controls/HelpControls.qml
new file mode 100644
index 0000000000..b502f7524b
--- /dev/null
+++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/controls/HelpControls.qml
@@ -0,0 +1,91 @@
+//
+// HelpControls.qml
+//
+// Created by Zach Fox on 2019-08-07
+// Copyright 2019 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+import "../../simplifiedConstants" as SimplifiedConstants
+import "../../simplifiedControls" as SimplifiedControls
+import stylesUit 1.0 as HifiStylesUit
+import QtQuick.Layouts 1.3
+import PerformanceEnums 1.0
+
+Flickable {
+ id: root
+ contentWidth: parent.width
+ contentHeight: controlsColumnLayout.height
+ clip: true
+
+ onVisibleChanged: {
+ if (visible) {
+ root.contentX = 0;
+ root.contentY = 0;
+ }
+ }
+
+ SimplifiedConstants.SimplifiedConstants {
+ id: simplifiedUI
+ }
+
+
+ Image {
+ id: accent
+ source: "../images/accent1.svg"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ width: 83
+ height: 156
+ transform: Scale {
+ xScale: -1
+ origin.x: accent.width / 2
+ origin.y: accent.height / 2
+ }
+ }
+
+
+ ColumnLayout {
+ id: controlsColumnLayout
+ anchors.left: parent.left
+ anchors.leftMargin: 26
+ anchors.right: parent.right
+ anchors.rightMargin: 26
+ anchors.top: parent.top
+ spacing: 0
+
+ HifiStylesUit.GraphikSemiBold {
+ text: "HQ Controls"
+ Layout.maximumWidth: parent.width
+ Layout.topMargin: 16
+ height: paintedHeight
+ size: 22
+ color: simplifiedUI.colors.text.white
+ }
+
+ HifiStylesUit.GraphikRegular {
+ text: "You can use the following controls to move your avatar around your HQ:"
+ Layout.maximumWidth: parent.width
+ wrapMode: Text.Wrap
+ height: paintedHeight
+ size: 18
+ color: simplifiedUI.colors.text.white
+ }
+
+ SimplifiedControls.Button {
+ Layout.topMargin: 8
+ width: 200
+ height: 32
+ text: "VIEW ALL CONTROLS"
+ temporaryText: "Viewing!"
+
+ onClicked: {
+ Qt.openUrlExternally("http://docs.highfidelity.com/en/rc83/explore/get-started/desktop.html");
+ }
+ }
+ }
+}
diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent1.svg b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent1.svg
new file mode 100644
index 0000000000..885edef5ac
--- /dev/null
+++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent1.svg
@@ -0,0 +1,4 @@
+
diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent2.svg b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent2.svg
new file mode 100644
index 0000000000..027d9bb623
--- /dev/null
+++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent2.svg
@@ -0,0 +1,4 @@
+
diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent3.svg b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent3.svg
new file mode 100644
index 0000000000..07cc23ef1e
--- /dev/null
+++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/images/accent3.svg
@@ -0,0 +1,4 @@
+
diff --git a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml
index acabbe9485..209966dee3 100644
--- a/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml
+++ b/interface/resources/qml/hifi/simplifiedUI/topBar/SimplifiedTopBar.qml
@@ -352,7 +352,7 @@ Rectangle {
Item {
id: hmdButtonContainer
anchors.verticalCenter: parent.verticalCenter
- anchors.right: settingsButtonContainer.left
+ anchors.right: helpButtonContainer.left
anchors.rightMargin: 8
width: 48
height: width
@@ -417,6 +417,48 @@ Rectangle {
}
+ Item {
+ id: helpButtonContainer
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: settingsButtonContainer.left
+ anchors.rightMargin: 3
+ width: 36
+ height: width
+
+ Image {
+ id: helpButtonImage
+ source: "./images/settings.svg"
+ anchors.centerIn: parent
+ width: 22
+ height: 22
+ visible: false
+ }
+
+ ColorOverlay {
+ opacity: helpButtonMouseArea.containsMouse ? 1.0 : 0.7
+ anchors.fill: helpButtonImage
+ source: helpButtonImage
+ color: simplifiedUI.colors.text.white
+ }
+
+ MouseArea {
+ id: helpButtonMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: {
+ Tablet.playSound(TabletEnums.ButtonHover);
+ }
+ onClicked: {
+ Tablet.playSound(TabletEnums.ButtonClick);
+ sendToScript({
+ "source": "SimplifiedTopBar.qml",
+ "method": "toggleHelpApp"
+ });
+ }
+ }
+ }
+
+
Item {
id: settingsButtonContainer
diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js
index f4f2627c66..84d5d55e0d 100644
--- a/scripts/simplifiedUI/ui/simplifiedUI.js
+++ b/scripts/simplifiedUI/ui/simplifiedUI.js
@@ -187,6 +187,71 @@ function toggleSettingsApp() {
settingsAppWindow.closed.connect(onSettingsAppClosed);
}
+
+var HELP_APP_MESSAGE_SOURCE = "HelpApp.qml";
+function onMessageFromHelpApp(message) {
+ if (message.source !== HELP_APP_MESSAGE_SOURCE) {
+ return;
+ }
+
+ switch (message.method) {
+
+ default:
+ console.log("Unrecognized message from " + HELP_APP_MESSAGE_SOURCE + ": " + JSON.stringify(message));
+ break;
+ }
+}
+
+
+function onHelpAppClosed() {
+ if (helpAppWindow) {
+ helpAppWindow.fromQml.disconnect(onMessageFromHelpApp);
+ helpAppWindow.closed.disconnect(onHelpAppClosed);
+ }
+ helpAppWindow = false;
+}
+
+
+var HELP_APP_QML_PATH = Script.resourcesPath() + "qml/hifi/simplifiedUI/helpApp/HelpApp.qml";
+var HELP_APP_WINDOW_TITLE = "Help";
+var HELP_APP_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
+var HELP_APP_WIDTH_PX = 480;
+var HELP_APP_HEIGHT_PX = 615;
+var HELP_APP_WINDOW_FLAGS = 0x00000001 | // Qt::Window
+ 0x00001000 | // Qt::WindowTitleHint
+ 0x00002000 | // Qt::WindowSystemMenuHint
+ 0x08000000 | // Qt::WindowCloseButtonHint
+ 0x00008000 | // Qt::WindowMaximizeButtonHint
+ 0x00004000; // Qt::WindowMinimizeButtonHint
+var helpAppWindow = false;
+function toggleHelpApp() {
+ if (helpAppWindow) {
+ helpAppWindow.close();
+ // This really shouldn't be necessary.
+ // This signal really should automatically be called by the signal handler set up below.
+ // But fixing that requires an engine change, so this workaround will do.
+ onHelpAppClosed();
+ return;
+ }
+
+ helpAppWindow = Desktop.createWindow(HELP_APP_QML_PATH, {
+ title: HELP_APP_WINDOW_TITLE,
+ presentationMode: HELP_APP_PRESENTATION_MODE,
+ size: {
+ x: HELP_APP_WIDTH_PX,
+ y: HELP_APP_HEIGHT_PX
+ },
+ position: {
+ x: Math.max(Window.x + POPOUT_SAFE_MARGIN_X, Window.x + Window.innerWidth / 2 - HELP_APP_WIDTH_PX / 2),
+ y: Math.max(Window.y + POPOUT_SAFE_MARGIN_Y, Window.y + Window.innerHeight / 2 - HELP_APP_HEIGHT_PX / 2)
+ },
+ overrideFlags: HELP_APP_WINDOW_FLAGS
+ });
+
+ helpAppWindow.fromQml.connect(onMessageFromHelpApp);
+ helpAppWindow.closed.connect(onHelpAppClosed);
+}
+
function updateEmoteAppBarPosition() {
if (!emoteAppBarWindow) {
return;
@@ -374,6 +439,10 @@ function onMessageFromTopBar(message) {
toggleSettingsApp();
break;
+ case "toggleHelpApp":
+ toggleHelpApp();
+ break;
+
case "setOutputMuted":
setOutputMuted(message.data.outputMuted);
break;