overte-thingvellir/interface/resources/qml/InteractiveWindow.qml
2018-06-28 19:04:08 +02:00

283 lines
9 KiB
QML

//
// InteractiveWindow.qml
//
// Created by Thijs Wenker on 2018-06-25
// Copyright 2018 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.3
import InteractiveWindowFlags 1.0
import "windows" as Windows
import "controls"
import "controls-uit" as Controls
import "styles"
import "styles-uit"
Windows.Window {
id: root;
HifiConstants { id: hifi }
title: "InteractiveWindow";
resizable: true;
// Virtual window visibility
shown: false;
focus: true;
property var channel;
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
destroyOnCloseButton: false;
property var flags: 0;
property var source;
property var dynamicContent;
property var nativeWindow;
// custom visibility flag for interactiveWindow to proxy virtualWindow.shown / nativeWindow.visible
property var interactiveWindowVisible: true;
property point interactiveWindowPosition;
property size interactiveWindowSize;
// Keyboard control properties in case needed by QML content.
property bool keyboardEnabled: false;
property bool keyboardRaised: false;
property bool punctuationMode: false;
readonly property int modeNotSet: 0;
readonly property int modeNative: 1;
readonly property int modeVirtual: 2;
property int windowMode: modeNotSet;
property bool forceNative: false;
property bool forceVirtual: false;
property string windowModeText: getModeString();
function getModeString() {
switch (windowMode) {
case modeNotSet:
return "none";
case modeNative:
return "native";
case modeVirtual:
return "virtual";
}
return "unknown";
}
onWindowModeChanged: {
windowModeText = getModeString();
}
onSourceChanged: {
if (dynamicContent) {
dynamicContent.destroy();
dynamicContent = null;
}
QmlSurface.load(source, contentHolder, function(newObject) {
dynamicContent = newObject;
if (dynamicContent && dynamicContent.anchors) {
dynamicContent.anchors.fill = contentHolder;
}
});
}
function updateInteractiveWindowPositionForMode() {
if (windowMode === modeVirtual) {
x = interactiveWindowPosition.x;
y = interactiveWindowPosition.y;
} else if (windowMode === modeVirtual && nativeWindow) {
nativeWindow.x = interactiveWindowPosition.x;
nativeWindow.y = interactiveWindowPosition.y;
}
}
function updateInteractiveWindowSizeForMode() {
if (windowMode === modeVirtual) {
width = interactiveWindowSize.width;
height = interactiveWindowSize.height;
} else if (windowMode === modeVirtual && nativeWindow) {
nativeWindow.width = interactiveWindowSize.width;
nativeWindow.height = interactiveWindowSize.heigth;
}
}
function trySwitchWindowMode() {
if (windowMode !== modeVirtual && (HMD.active || (forceVirtual && !forceNative))) {
windowMode = modeVirtual;
if (nativeWindow) {
nativeWindow.setVisible(false);
}
contentHolder.parent = root;
updateInteractiveWindowPositionForMode();
shown = interactiveWindowVisible;
} else if (windowMode !== modeNative && (!HMD.active || (forceNative && !forceVirtual))) {
windowMode = modeNative;
shown = false;
if (nativeWindow) {
contentHolder.parent = nativeWindow.contentItem;
nativeWindow.setVisible(interactiveWindowVisible);
updateInteractiveWindowPositionForMode();
}
} else if (windowMode === modeNotSet) {
console.error("windowMode should be set.");
}
}
function displayModeChanged(isHMD) {
trySwitchWindowMode();
}
Component.onCompleted: {
HMD.displayModeChanged.connect(displayModeChanged);
forceVirtual = (flags & InteractiveWindowFlags.ForceVirtual) === InteractiveWindowFlags.ForceVirtual;
forceNative = (flags & InteractiveWindowFlags.ForceNative) === InteractiveWindowFlags.ForceNative;
x = interactiveWindowPosition.x;
y = interactiveWindowPosition.y;
width = interactiveWindowSize.width;
height = interactiveWindowSize.height;
if (!forceVirtual || (forceVirtual && forceNative)) {
nativeWindow = Qt.createQmlObject('
import QtQuick 2.3;
import QtQuick.Window 2.3;
Window {
id: root;
Rectangle {
color: hifi.colors.baseGray
anchors.fill: parent
}
}', root, 'InteractiveWindow.qml->nativeWindow');
nativeWindow.title = root.title;
var nativeWindowFlags = Qt.Window |
Qt.WindowTitleHint |
Qt.WindowSystemMenuHint |
Qt.WindowCloseButtonHint |
Qt.WindowMaximizeButtonHint |
Qt.WindowMinimizeButtonHint;
if ((flags & InteractiveWindowFlags.AlwaysOnTop) === InteractiveWindowFlags.AlwaysOnTop) {
nativeWindowFlags |= Qt.WindowStaysOnTopHint;
}
nativeWindow.flags = nativeWindowFlags;
nativeWindow.x = interactiveWindowPosition.x;
nativeWindow.y = interactiveWindowPosition.y;
nativeWindow.width = interactiveWindowSize.width;
nativeWindow.height = interactiveWindowSize.height;
nativeWindow.xChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowPosition = Qt.point(nativeWindow.x, interactiveWindowPosition.y);
}
});
nativeWindow.yChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowPosition = Qt.point(interactiveWindowPosition.x, nativeWindow.y);
}
});
nativeWindow.widthChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowSize = Qt.size(nativeWindow.width, interactiveWindowSize.height);
}
});
nativeWindow.heightChanged.connect(function() {
if (windowMode === modeNative && nativeWindow.visible) {
interactiveWindowSize = Qt.size(interactiveWindowSize.width, nativeWindow.height);
}
});
}
// finally set the initial window mode:
trySwitchWindowMode();
}
// Handle message traffic from the script that launched us to the loaded QML
function fromScript(message) {
if (root.dynamicContent && root.dynamicContent.fromScript) {
root.dynamicContent.fromScript(message);
}
}
function show() {
interactiveWindowVisible = true;
raiseWindow();
}
function raiseWindow() {
if (windowMode === modeVirtual) {
raise();
} else if (windowMode === modeNative && nativeWindow) {
nativeWindow.raise();
}
}
// Handle message traffic from our loaded QML to the script that launched us
signal sendToScript(var message);
onDynamicContentChanged: {
if (dynamicContent && dynamicContent.sendToScript) {
dynamicContent.sendToScript.connect(sendToScript);
}
}
onInteractiveWindowVisibleChanged: {
if (windowMode === modeVirtual) {
shown = interactiveWindowVisible;
} else if (windowMode === modeNative && nativeWindow) {
nativeWindow.setVisible(interactiveWindowVisible);
}
}
onTitleChanged: {
if (nativeWindow) {
nativeWindow.title = title;
}
}
onXChanged: {
if (windowMode === modeVirtual) {
interactiveWindowPosition = Qt.point(x, interactiveWindowPosition.y);
}
}
onYChanged: {
if (windowMode === modeVirtual) {
interactiveWindowPosition = Qt.point(interactiveWindowPosition.x, y);
}
}
onWidthChanged: {
if (windowMode === modeVirtual) {
interactiveWindowSize = Qt.size(width, interactiveWindowSize.height);
}
}
onHeightChanged: {
if (windowMode === modeVirtual) {
interactiveWindowSize = Qt.size(interactiveWindowSize.width, height);
}
}
onInteractiveWindowPositionChanged: {
updateInteractiveWindowPositionForMode();
}
onInteractiveWindowSizeChanged: {
updateInteractiveWindowSizeForMode();
}
Item {
id: contentHolder
anchors.fill: parent
}
}