overte-HifiExperiments/interface/resources/qml/desktop/Desktop.qml

291 lines
8.5 KiB
QML

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2 as OriginalDialogs;
import "../dialogs"
import "../menus"
import "../js/Utils.js" as Utils
// This is our primary 'desktop' object to which all VR dialogs and
// windows will be childed.
FocusScope {
id: desktop
anchors.fill: parent;
objectName: "desktop"
// Allows QML/JS to find the desktop through the parent chain
property bool desktopRoot: true
// The VR version of the primary menu
property var rootMenu: Menu { objectName: "rootMenu" }
readonly property alias zLevels: zLevels
QtObject {
id: zLevels;
readonly property real normal: 0
readonly property real top: 2000
readonly property real modal: 4000
readonly property real menu: 8000
}
QtObject {
id: d
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 findParentMatching(item, predicate) {
while (item) {
if (predicate(item)) {
break;
}
item = item.parent;
}
return item;
}
function isDesktop(item) {
return item.desktopRoot;
}
function isTopLevelWindow(item) {
return item.topLevelWindow;
}
function isAlwaysOnTopWindow(window) {
return window.alwaysOnTop;
}
function isModalWindow(window) {
return window.modality !== Qt.NonModal;
}
function getTopLevelWindows(predicate) {
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 (isTopLevelWindow(child) && (!predicate || predicate(child))) {
currentWindows.push(child)
}
}
return currentWindows;
}
function getDesktopWindow(item) {
return findParentMatching(item, isTopLevelWindow)
}
function fixupZOrder(windows, basis, topWindow) {
windows.sort(function(a, b){ return a.z - b.z; });
if ((topWindow.z >= basis) && (windows[windows.length - 1] === topWindow)) {
return;
}
var lastZ = -1;
var lastTargetZ = basis - 1;
for (var i = 0; i < windows.length; ++i) {
var window = windows[i];
if (!window.visible) {
continue
}
if (topWindow && (topWindow === window)) {
continue
}
if (window.z > lastZ) {
lastZ = window.z;
++lastTargetZ;
}
if (DebugQML) {
console.log("Assigning z order " + lastTargetZ + " to " + window)
}
window.z = lastTargetZ;
}
if (topWindow) {
++lastTargetZ;
if (DebugQML) {
console.log("Assigning z order " + lastTargetZ + " to " + topWindow)
}
topWindow.z = lastTargetZ;
}
return lastTargetZ;
}
function raiseWindow(targetWindow) {
var predicate;
var zBasis;
if (isModalWindow(targetWindow)) {
predicate = isModalWindow;
zBasis = zLevels.modal
} else if (isAlwaysOnTopWindow(targetWindow)) {
predicate = function(window) {
return (isAlwaysOnTopWindow(window) && !isModalWindow(window));
}
zBasis = zLevels.top
} else {
predicate = function(window) {
return (!isAlwaysOnTopWindow(window) && !isModalWindow(window));
}
zBasis = zLevels.normal
}
var windows = getTopLevelWindows(predicate);
fixupZOrder(windows, zBasis, targetWindow);
}
}
function raise(item) {
var targetWindow = d.getDesktopWindow(item);
if (!targetWindow) {
console.warn("Could not find top level window for " + item);
return;
}
// Fix up the Z-order (takes into account if this is a modal window)
d.raiseWindow(targetWindow);
var setFocus = true;
if (!d.isModalWindow(targetWindow)) {
var modalWindows = d.getTopLevelWindows(d.isModalWindow);
if (modalWindows.length) {
setFocus = false;
}
}
if (setFocus) {
targetWindow.focus = true;
}
reposition(targetWindow);
}
function reposition(item) {
if (desktop.width === 0 || desktop.height === 0) {
return;
}
var targetWindow = d.getDesktopWindow(item);
if (!targetWindow) {
console.warn("Could not find top level window for " + item);
return;
}
var windowRect = targetWindow.framedRect();
var minPosition = Qt.vector2d(-windowRect.x, -windowRect.y);
var maxPosition = Qt.vector2d(desktop.width - windowRect.width, desktop.height - windowRect.height);
var newPosition;
if (targetWindow.x === -1 && targetWindow.y === -1) {
// Set initial window position
newPosition = Utils.randomPosition(minPosition, maxPosition);
} else {
newPosition = Utils.clampVector(Qt.vector2d(targetWindow.x, targetWindow.y), minPosition, maxPosition);
}
targetWindow.x = newPosition.x;
targetWindow.y = newPosition.y;
}
function repositionAll() {
var windows = d.getTopLevelWindows();
for (var i = 0; i < windows.length; ++i) {
reposition(windows[i]);
}
}
onHeightChanged: repositionAll();
onWidthChanged: repositionAll();
Component { id: messageDialogBuilder; MessageDialog { } }
function messageBox(properties) {
return messageDialogBuilder.createObject(desktop, properties);
}
Component { id: queryDialogBuilder; QueryDialog { } }
function queryBox(properties) {
return queryDialogBuilder.createObject(desktop, properties);
}
MenuMouseHandler { id: menuPopperUpper }
function popupMenu(point) {
menuPopperUpper.popup(desktop, rootMenu.items, point);
}
function toggleMenu(point) {
menuPopperUpper.toggle(desktop, rootMenu.items, point);
}
Keys.onEscapePressed: {
if (menuPopperUpper.closeLastMenu()) {
event.accepted = true;
return;
}
event.accepted = false;
}
Keys.onLeftPressed: {
if (menuPopperUpper.closeLastMenu()) {
event.accepted = true;
return;
}
event.accepted = false;
}
function unfocusWindows() {
var windows = d.getTopLevelWindows();
for (var i = 0; i < windows.length; ++i) {
windows[i].focus = false;
}
desktop.focus = true;
}
// Debugging help for figuring out focus issues
property var offscreenWindow;
onOffscreenWindowChanged: {
offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged);
focusHack.start();
}
FocusHack { id: focusHack; }
function onWindowFocusChanged() {
console.log("Focus item is " + offscreenWindow.activeFocusItem);
var focusedItem = offscreenWindow.activeFocusItem ;
if (DebugQML && focusedItem) {
var rect = desktop.mapFromItem(focusedItem, 0, 0, focusedItem.width, focusedItem.height);
focusDebugger.x = rect.x;
focusDebugger.y = rect.y;
focusDebugger.width = rect.width
focusDebugger.height = rect.height
}
}
Rectangle {
id: focusDebugger;
z: 9999; visible: false; color: "red"
ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 }
}
Action {
text: "Toggle Focus Debugger"
shortcut: "Ctrl+Shift+F"
enabled: DebugQML
onTriggered: focusDebugger.visible = !focusDebugger.visible
}
}