mirror of
https://github.com/overte-org/overte.git
synced 2025-04-07 13:32:35 +02:00
335 lines
12 KiB
QML
335 lines
12 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 "windows" as Windows
|
|
import "controls"
|
|
import controlsUit 1.0 as Controls
|
|
import "styles"
|
|
import stylesUit 1.0
|
|
|
|
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;
|
|
|
|
signal selfDestruct();
|
|
|
|
property var additionalFlags: 0;
|
|
property var overrideFlags: 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;
|
|
|
|
property int presentationMode: 0;
|
|
|
|
property var initialized: false;
|
|
onSourceChanged: {
|
|
if (dynamicContent) {
|
|
dynamicContent.destroy();
|
|
dynamicContent = null;
|
|
}
|
|
QmlSurface.load(source, contentHolder, function(newObject) {
|
|
dynamicContent = newObject;
|
|
updateInteractiveWindowSizeForMode();
|
|
if (dynamicContent && dynamicContent.anchors) {
|
|
dynamicContent.anchors.fill = contentHolder;
|
|
}
|
|
});
|
|
}
|
|
|
|
Timer {
|
|
id: timer
|
|
interval: 500;
|
|
repeat: false;
|
|
onTriggered: {
|
|
updateContentParent();
|
|
}
|
|
}
|
|
|
|
function updateInteractiveWindowPositionForMode() {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
x = interactiveWindowPosition.x;
|
|
y = interactiveWindowPosition.y;
|
|
} else if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow) {
|
|
if (interactiveWindowPosition.x === 0 && interactiveWindowPosition.y === 0) {
|
|
// default position for native window in center of main application window
|
|
nativeWindow.x = Math.floor(Window.x + (Window.innerWidth / 2) - (interactiveWindowSize.width / 2));
|
|
nativeWindow.y = Math.floor(Window.y + (Window.innerHeight / 2) - (interactiveWindowSize.height / 2));
|
|
} else {
|
|
nativeWindow.x = interactiveWindowPosition.x;
|
|
nativeWindow.y = interactiveWindowPosition.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateInteractiveWindowSizeForMode() {
|
|
root.width = interactiveWindowSize.width;
|
|
root.height = interactiveWindowSize.height;
|
|
contentHolder.width = interactiveWindowSize.width;
|
|
contentHolder.height = interactiveWindowSize.height;
|
|
|
|
if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow) {
|
|
nativeWindow.width = interactiveWindowSize.width;
|
|
nativeWindow.height = interactiveWindowSize.height;
|
|
}
|
|
}
|
|
|
|
function updateContentParent() {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
contentHolder.parent = root;
|
|
} else if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow) {
|
|
contentHolder.parent = nativeWindow.contentItem;
|
|
}
|
|
}
|
|
|
|
function setupPresentationMode() {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
if (nativeWindow) {
|
|
nativeWindow.setVisible(false);
|
|
}
|
|
updateInteractiveWindowPositionForMode();
|
|
shown = interactiveWindowVisible;
|
|
} else if (presentationMode === Desktop.PresentationMode.NATIVE) {
|
|
shown = false;
|
|
if (nativeWindow) {
|
|
updateInteractiveWindowPositionForMode();
|
|
nativeWindow.setVisible(interactiveWindowVisible);
|
|
}
|
|
} else if (presentationMode === modeNotSet) {
|
|
console.error("presentationMode should be set.");
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
|
|
x = interactiveWindowPosition.x;
|
|
y = interactiveWindowPosition.y;
|
|
width = interactiveWindowSize.width;
|
|
height = interactiveWindowSize.height;
|
|
|
|
nativeWindow = Qt.createQmlObject('
|
|
import QtQuick 2.3;
|
|
import QtQuick.Window 2.3;
|
|
|
|
Window {
|
|
id: root;
|
|
width: interactiveWindowSize.width
|
|
height: interactiveWindowSize.height
|
|
// fix for missing content on OSX initial startup with a non-maximized interface window. It seems that in this case, we cannot update
|
|
// the content parent during creation of the Window root. This added delay will update the parent after the root has finished loading.
|
|
Component.onCompleted: {
|
|
timer.start();
|
|
}
|
|
|
|
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;
|
|
// only use the always on top feature for non Windows OS
|
|
if (Qt.platform.os !== "windows" && (root.additionalFlags & Desktop.ALWAYS_ON_TOP)) {
|
|
nativeWindowFlags |= Qt.WindowStaysOnTopHint;
|
|
}
|
|
nativeWindow.flags = root.overrideFlags || nativeWindowFlags;
|
|
|
|
nativeWindow.x = interactiveWindowPosition.x;
|
|
nativeWindow.y = interactiveWindowPosition.y;
|
|
|
|
nativeWindow.width = interactiveWindowSize.width;
|
|
nativeWindow.height = interactiveWindowSize.height;
|
|
|
|
nativeWindow.xChanged.connect(function() {
|
|
if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow.visible) {
|
|
interactiveWindowPosition = Qt.point(nativeWindow.x, interactiveWindowPosition.y);
|
|
}
|
|
});
|
|
|
|
nativeWindow.yChanged.connect(function() {
|
|
if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow.visible) {
|
|
interactiveWindowPosition = Qt.point(interactiveWindowPosition.x, nativeWindow.y);
|
|
}
|
|
});
|
|
|
|
nativeWindow.widthChanged.connect(function() {
|
|
if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow.visible) {
|
|
interactiveWindowSize = Qt.size(nativeWindow.width, interactiveWindowSize.height);
|
|
}
|
|
});
|
|
|
|
nativeWindow.heightChanged.connect(function() {
|
|
if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow.visible) {
|
|
interactiveWindowSize = Qt.size(interactiveWindowSize.width, nativeWindow.height);
|
|
}
|
|
});
|
|
|
|
nativeWindow.closing.connect(function(closeEvent) {
|
|
closeEvent.accepted = false;
|
|
windowClosed();
|
|
});
|
|
|
|
// finally set the initial window mode:
|
|
setupPresentationMode();
|
|
updateContentParent();
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
// 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 (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
raise();
|
|
} else if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow) {
|
|
nativeWindow.raise();
|
|
}
|
|
}
|
|
|
|
// Handle message traffic from our loaded QML to the script that launched us
|
|
signal sendToScript(var message);
|
|
|
|
// Children of this InteractiveWindow Item are able to request a new width and height
|
|
// for the parent Item (this one) and its associated C++ InteractiveWindow using these methods.
|
|
function onRequestNewWidth(newWidth) {
|
|
interactiveWindowSize.width = newWidth;
|
|
updateInteractiveWindowSizeForMode();
|
|
}
|
|
function onRequestNewHeight(newHeight) {
|
|
interactiveWindowSize.height = newHeight;
|
|
updateInteractiveWindowSizeForMode();
|
|
}
|
|
|
|
// These signals are used to forward key-related events from the QML to the C++.
|
|
signal keyPressEvent(int key, int modifiers);
|
|
signal keyReleaseEvent(int key, int modifiers);
|
|
|
|
onDynamicContentChanged: {
|
|
if (dynamicContent && dynamicContent.sendToScript) {
|
|
dynamicContent.sendToScript.connect(sendToScript);
|
|
}
|
|
|
|
if (dynamicContent && dynamicContent.requestNewWidth) {
|
|
dynamicContent.requestNewWidth.connect(onRequestNewWidth);
|
|
}
|
|
|
|
if (dynamicContent && dynamicContent.requestNewHeight) {
|
|
dynamicContent.requestNewHeight.connect(onRequestNewHeight);
|
|
}
|
|
|
|
if (dynamicContent && dynamicContent.keyPressEvent) {
|
|
dynamicContent.keyPressEvent.connect(keyPressEvent);
|
|
}
|
|
|
|
if (dynamicContent && dynamicContent.keyReleaseEvent) {
|
|
dynamicContent.keyReleaseEvent.connect(keyReleaseEvent);
|
|
}
|
|
}
|
|
|
|
onInteractiveWindowVisibleChanged: {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
shown = interactiveWindowVisible;
|
|
} else if (presentationMode === Desktop.PresentationMode.NATIVE && nativeWindow) {
|
|
if (!nativeWindow.visible && interactiveWindowVisible) {
|
|
nativeWindow.showNormal();
|
|
} else {
|
|
nativeWindow.setVisible(interactiveWindowVisible);
|
|
}
|
|
}
|
|
}
|
|
|
|
onTitleChanged: {
|
|
if (nativeWindow) {
|
|
nativeWindow.title = title;
|
|
}
|
|
}
|
|
|
|
onXChanged: {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
interactiveWindowPosition = Qt.point(x, interactiveWindowPosition.y);
|
|
}
|
|
}
|
|
|
|
onYChanged: {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
interactiveWindowPosition = Qt.point(interactiveWindowPosition.x, y);
|
|
}
|
|
}
|
|
|
|
onWidthChanged: {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
interactiveWindowSize = Qt.size(width, interactiveWindowSize.height);
|
|
}
|
|
}
|
|
|
|
onHeightChanged: {
|
|
if (presentationMode === Desktop.PresentationMode.VIRTUAL) {
|
|
interactiveWindowSize = Qt.size(interactiveWindowSize.width, height);
|
|
}
|
|
}
|
|
|
|
onPresentationModeChanged: {
|
|
if (initialized) {
|
|
setupPresentationMode();
|
|
updateContentParent();
|
|
}
|
|
}
|
|
|
|
onWindowClosed: {
|
|
// set invisible on close, to make it not re-appear unintended after switching PresentationMode
|
|
interactiveWindowVisible = false;
|
|
|
|
if ((root.additionalFlags & Desktop.CLOSE_BUTTON_HIDES) !== Desktop.CLOSE_BUTTON_HIDES) {
|
|
selfDestruct();
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: contentHolder
|
|
anchors.fill: parent
|
|
}
|
|
}
|