mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 20:58:38 +02:00
Address some z-ordering issues in overlay windows
This commit is contained in:
parent
95f821d61a
commit
1b82200ecb
7 changed files with 206 additions and 33 deletions
|
@ -8,33 +8,6 @@ qmlWindow = new OverlayWindow({
|
||||||
visible: true
|
visible: true
|
||||||
});
|
});
|
||||||
|
|
||||||
//qmlWindow.eventBridge.webEventReceived.connect(function(data) {
|
Script.setInterval(function() {
|
||||||
// print("JS Side event received: " + data);
|
qmlWindow.raise();
|
||||||
//});
|
}, 2 * 1000);
|
||||||
//
|
|
||||||
//var titles = ["A", "B", "C"];
|
|
||||||
//var titleIndex = 0;
|
|
||||||
//
|
|
||||||
//Script.setInterval(function() {
|
|
||||||
// qmlWindow.eventBridge.emitScriptEvent("JS Event sent");
|
|
||||||
// var size = qmlWindow.size;
|
|
||||||
// var position = qmlWindow.position;
|
|
||||||
// print("Window visible: " + qmlWindow.visible)
|
|
||||||
// if (qmlWindow.visible) {
|
|
||||||
// print("Window size: " + size.x + "x" + size.y)
|
|
||||||
// print("Window pos: " + position.x + "x" + position.y)
|
|
||||||
// qmlWindow.setVisible(false);
|
|
||||||
// } else {
|
|
||||||
// qmlWindow.setVisible(true);
|
|
||||||
// qmlWindow.setTitle(titles[titleIndex]);
|
|
||||||
// qmlWindow.setSize(320 + Math.random() * 100, 240 + Math.random() * 100);
|
|
||||||
// titleIndex += 1;
|
|
||||||
// titleIndex %= titles.length;
|
|
||||||
// }
|
|
||||||
//}, 2 * 1000);
|
|
||||||
//
|
|
||||||
//Script.setTimeout(function() {
|
|
||||||
// print("Closing script");
|
|
||||||
// qmlWindow.close();
|
|
||||||
// Script.stop();
|
|
||||||
//}, 15 * 1000)
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import "styles"
|
||||||
DialogContainer {
|
DialogContainer {
|
||||||
id: root
|
id: root
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
|
z: 1000
|
||||||
|
|
||||||
objectName: "AddressBarDialog"
|
objectName: "AddressBarDialog"
|
||||||
|
|
||||||
|
|
165
interface/resources/qml/Global.js
Normal file
165
interface/resources/qml/Global.js
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
var OFFSCREEN_ROOT_OBJECT_NAME = "desktopRoot"
|
||||||
|
var OFFSCREEN_WINDOW_OBJECT_NAME = "topLevelWindow"
|
||||||
|
|
||||||
|
function findChild(item, name) {
|
||||||
|
for (var i = 0; i < item.children.length; ++i) {
|
||||||
|
if (item.children[i].objectName === name) {
|
||||||
|
return item.children[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findParent(item, name) {
|
||||||
|
while (item) {
|
||||||
|
if (item.objectName === name) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
item = item.parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDesktop(item) {
|
||||||
|
return findParent(item, OFFSCREEN_ROOT_OBJECT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findRootMenu(item) {
|
||||||
|
item = getDesktop(item);
|
||||||
|
return item ? item.rootMenu : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getTopLevelWindows(item) {
|
||||||
|
var desktop = getDesktop(item);
|
||||||
|
var currentWindows = [];
|
||||||
|
if (!desktop) {
|
||||||
|
console.log("Could not find desktop for " + item)
|
||||||
|
return currentWindows;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < desktop.children.length; ++i) {
|
||||||
|
var child = desktop.children[i];
|
||||||
|
if (Global.OFFSCREEN_WINDOW_OBJECT_NAME === child.objectName) {
|
||||||
|
var windowId = child.toString();
|
||||||
|
currentWindows.push(child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentWindows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getDesktopWindow(item) {
|
||||||
|
item = findParent(item, OFFSCREEN_WINDOW_OBJECT_NAME);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeWindow(item) {
|
||||||
|
item = findDialog(item);
|
||||||
|
if (item) {
|
||||||
|
item.enabled = false
|
||||||
|
} else {
|
||||||
|
console.warn("Could not find top level dialog")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findMenuChild(menu, childName) {
|
||||||
|
if (!menu) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menu.type !== 2) {
|
||||||
|
console.warn("Tried to find child of a non-menu");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = menu.items;
|
||||||
|
var count = items.length;
|
||||||
|
for (var i = 0; i < count; ++i) {
|
||||||
|
var child = items[i];
|
||||||
|
var name;
|
||||||
|
switch (child.type) {
|
||||||
|
case 2:
|
||||||
|
name = child.title;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
name = child.text;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name && name === childName) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findMenu(rootMenu, path) {
|
||||||
|
if ('string' === typeof(path)) {
|
||||||
|
path = [ path ]
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentMenu = rootMenu;
|
||||||
|
for (var i = 0; currentMenu && i < path.length; ++i) {
|
||||||
|
currentMenu = findMenuChild(currentMenu, path[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findInRootMenu(item, path) {
|
||||||
|
return findMenu(findRootMenu(item), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function menuItemsToListModel(parent, items) {
|
||||||
|
var newListModel = Qt.createQmlObject('import QtQuick 2.5; ListModel {}', parent);
|
||||||
|
for (var i = 0; i < items.length; ++i) {
|
||||||
|
var item = items[i];
|
||||||
|
switch (item.type) {
|
||||||
|
case 2:
|
||||||
|
newListModel.append({"type":item.type, "name": item.title, "item": item})
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
newListModel.append({"type":item.type, "name": item.text, "item": item})
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
newListModel.append({"type":item.type, "name": "-----", "item": item})
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newListModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
function raiseWindow(item) {
|
||||||
|
var targetWindow = getDesktopWindow(item);
|
||||||
|
if (!targetWindow) {
|
||||||
|
console.warn("Could not find top level window for " + item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var desktop = getDesktop(targetWindow);
|
||||||
|
if (!desktop) {
|
||||||
|
//console.warn("Could not find desktop for window " + targetWindow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxZ = 0;
|
||||||
|
var minZ = 100000;
|
||||||
|
var windows = desktop.windows;
|
||||||
|
windows.sort(function(a, b){
|
||||||
|
return a.z - b.z;
|
||||||
|
});
|
||||||
|
var lastZ = -1;
|
||||||
|
var lastTargetZ = -1;
|
||||||
|
for (var i = 0; i < windows.length; ++i) {
|
||||||
|
var window = windows[i];
|
||||||
|
if (window.z > lastZ) {
|
||||||
|
lastZ = window.z;
|
||||||
|
++lastTargetZ;
|
||||||
|
}
|
||||||
|
window.z = lastTargetZ;
|
||||||
|
}
|
||||||
|
targetWindow.z = lastTargetZ + 1;
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ import QtWebChannel 1.0
|
||||||
import QtWebSockets 1.0
|
import QtWebSockets 1.0
|
||||||
import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel
|
import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel
|
||||||
|
|
||||||
|
import "Global.js" as Global
|
||||||
|
|
||||||
import "controls"
|
import "controls"
|
||||||
import "styles"
|
import "styles"
|
||||||
|
|
||||||
|
@ -23,6 +25,10 @@ VrDialog {
|
||||||
contentImplicitWidth: clientArea.implicitWidth
|
contentImplicitWidth: clientArea.implicitWidth
|
||||||
contentImplicitHeight: clientArea.implicitHeight
|
contentImplicitHeight: clientArea.implicitHeight
|
||||||
property alias source: pageLoader.source
|
property alias source: pageLoader.source
|
||||||
|
|
||||||
|
function raiseWindow() {
|
||||||
|
Global.raiseWindow(root)
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: clientArea
|
id: clientArea
|
||||||
|
|
|
@ -2,16 +2,23 @@ import Hifi 1.0
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
|
import "Global.js" as Global
|
||||||
|
|
||||||
// This is our primary 'window' object to which all dialogs and controls will
|
// This is our primary 'window' object to which all dialogs and controls will
|
||||||
// be childed.
|
// be childed.
|
||||||
Root {
|
Root {
|
||||||
id: root
|
id: root
|
||||||
objectName: "desktopRoot"
|
objectName: Global.OFFSCREEN_ROOT_OBJECT_NAME
|
||||||
anchors.fill: parent
|
anchors.fill: parent;
|
||||||
|
property var windows: [];
|
||||||
property var rootMenu: Menu {
|
property var rootMenu: Menu {
|
||||||
objectName: "rootMenu"
|
objectName: "rootMenu"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChildrenChanged: {
|
||||||
|
windows = Global.getTopLevelWindows(root);
|
||||||
|
}
|
||||||
|
|
||||||
onParentChanged: {
|
onParentChanged: {
|
||||||
forceActiveFocus();
|
forceActiveFocus();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ import QtQuick.Controls 1.2
|
||||||
import "."
|
import "."
|
||||||
import "../styles"
|
import "../styles"
|
||||||
|
|
||||||
|
import "../Global.js" as Global
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME Need to create a client property here so that objects can be
|
* FIXME Need to create a client property here so that objects can be
|
||||||
* placed in it without having to think about positioning within the outer
|
* placed in it without having to think about positioning within the outer
|
||||||
|
@ -45,9 +47,18 @@ DialogBase {
|
||||||
// trigger making it visible.
|
// trigger making it visible.
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
visible = true;
|
visible = true;
|
||||||
|
if (root.parent) {
|
||||||
|
Global.raiseWindow(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onParentChanged: {
|
||||||
|
if (enabled && parent) {
|
||||||
|
Global.raiseWindow(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The actual animator
|
// The actual animator
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
|
@ -60,6 +71,12 @@ DialogBase {
|
||||||
onOpacityChanged: {
|
onOpacityChanged: {
|
||||||
visible = (opacity != 0.0);
|
visible = (opacity != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (visible) {
|
||||||
|
Global.raiseWindow(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Some dialogs should be destroyed when they become invisible,
|
// Some dialogs should be destroyed when they become invisible,
|
||||||
// so handle that
|
// so handle that
|
||||||
|
@ -118,6 +135,7 @@ DialogBase {
|
||||||
y: root.titleY
|
y: root.titleY
|
||||||
width: root.titleWidth
|
width: root.titleWidth
|
||||||
height: root.titleHeight
|
height: root.titleHeight
|
||||||
|
onClicked: Global.raiseWindow(root)
|
||||||
|
|
||||||
drag {
|
drag {
|
||||||
target: root
|
target: root
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
#include <QtQuick/QQuickItem>
|
#include <QtQuick/QQuickItem>
|
||||||
|
#include <QtQml/QQmlContext>
|
||||||
|
#include <QtQml/QQmlEngine>
|
||||||
|
|
||||||
#include <QtWebSockets/QWebSocketServer>
|
#include <QtWebSockets/QWebSocketServer>
|
||||||
#include <QtWebSockets/QWebSocket>
|
#include <QtWebSockets/QWebSocket>
|
||||||
|
@ -141,6 +143,7 @@ QScriptValue QmlWindowClass::internalConstructor(const QString& qmlSource,
|
||||||
Q_ARG(std::function<void(QQmlContext*, QObject*)>, [&](QQmlContext* context, QObject* object) {
|
Q_ARG(std::function<void(QQmlContext*, QObject*)>, [&](QQmlContext* context, QObject* object) {
|
||||||
setupServer();
|
setupServer();
|
||||||
retVal = function(context, object);
|
retVal = function(context, object);
|
||||||
|
context->engine()->setObjectOwnership(retVal->_qmlWindow, QQmlEngine::CppOwnership);
|
||||||
registerObject(url.toLower(), retVal);
|
registerObject(url.toLower(), retVal);
|
||||||
if (!title.isEmpty()) {
|
if (!title.isEmpty()) {
|
||||||
retVal->setTitle(title);
|
retVal->setTitle(title);
|
||||||
|
@ -274,7 +277,7 @@ void QmlWindowClass::hasClosed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlWindowClass::raise() {
|
void QmlWindowClass::raise() {
|
||||||
// FIXME
|
QMetaObject::invokeMethod(_qmlWindow, "raiseWindow", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "QmlWindowClass.moc"
|
#include "QmlWindowClass.moc"
|
||||||
|
|
Loading…
Reference in a new issue