From 5fde166a38db4e993e6fd87e0b8d6f23ea6d12ee Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 22 Jan 2016 21:57:58 -0800 Subject: [PATCH 1/9] Fix menu Z-order --- interface/resources/qml/menus/MenuMouseHandler.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/menus/MenuMouseHandler.qml b/interface/resources/qml/menus/MenuMouseHandler.qml index c73730773f..d22b30e8d9 100644 --- a/interface/resources/qml/menus/MenuMouseHandler.qml +++ b/interface/resources/qml/menus/MenuMouseHandler.qml @@ -5,7 +5,7 @@ import "." Item { id: root - property int zBasis: 8192 - 1024 + property int zBasis: 9000 anchors.fill: parent MouseArea { @@ -93,7 +93,8 @@ Item { function buildMenu(items, targetPosition) { var model = toModel(items); - var newMenu = menuViewMaker.createObject(menuRoot, { model: model, z: topMenu ? topMenu.z + 1 : zBasis }); + // Menu's must be childed to desktop for Z-ordering + var newMenu = menuViewMaker.createObject(desktop, { model: model, z: topMenu ? topMenu.z + 1 : zBasis }); if (targetPosition) { newMenu.x = targetPosition.x newMenu.y = targetPosition.y - newMenu.height / 3 * 1 From d70faf598599a285975983c3b645191db1f02a55 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 10:01:56 -0800 Subject: [PATCH 2/9] Fix running scripts filter initial state --- interface/resources/qml/dialogs/RunningScripts.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/dialogs/RunningScripts.qml b/interface/resources/qml/dialogs/RunningScripts.qml index 7668d4e197..059c765f0e 100644 --- a/interface/resources/qml/dialogs/RunningScripts.qml +++ b/interface/resources/qml/dialogs/RunningScripts.qml @@ -202,6 +202,7 @@ Window { anchors.bottomMargin: 8 placeholderText: "filter" onTextChanged: scriptsModel.filterRegExp = new RegExp("^.*" + text + ".*$", "i") + Component.onCompleted: scriptsModel.filterRegExp = new RegExp("^.*$", "i") } TreeView { From 159794cafd8a3056213b65527a8cd745edd86ffe Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 12:07:01 -0800 Subject: [PATCH 3/9] Stop address bar stealing keyboard focus --- interface/resources/qml/AddressBarDialog.qml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 4bb8bcb8df..0af2400b8b 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -32,17 +32,6 @@ Window { implicitWidth: backgroundImage.width implicitHeight: backgroundImage.height - Timer { - running: root.visible - interval: 500 - repeat: true - onTriggered: { - if (root.enabled && !addressLine.activeFocus) { - addressLine.forceActiveFocus() - } - } - } - Image { id: backgroundImage From e52e35df8cf2bd2a802074cc43daa1579a37a20e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 12:09:15 -0800 Subject: [PATCH 4/9] Better initial window positioning --- interface/resources/qml/desktop/Desktop.qml | 97 ++++++++++++++----- interface/resources/qml/js/Utils.js | 16 +++ .../resources/qml/menus/MenuMouseHandler.qml | 3 +- interface/resources/qml/windows/Frame.qml | 3 +- interface/resources/qml/windows/Window.qml | 26 ++--- tests/ui/qml/main.qml | 2 +- 6 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 interface/resources/qml/js/Utils.js diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index eb80f2a7f4..cf6c22b8fd 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -4,6 +4,7 @@ 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. @@ -18,11 +19,18 @@ FocusScope { // 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 - readonly property int zBasisNormal: 0 - readonly property int zBasisAlwaysOnTop: 4096 - readonly property int zBasisModal: 8192 + readonly property var messageDialogBuilder: Component { MessageDialog { } } function findChild(item, name) { for (var i = 0; i < item.children.length; ++i) { @@ -75,15 +83,12 @@ FocusScope { return currentWindows; } - function getDesktopWindow(item) { return findParentMatching(item, isTopLevelWindow) } function fixupZOrder(windows, basis, topWindow) { - windows.sort(function(a, b){ - return a.z - b.z; - }); + windows.sort(function(a, b){ return a.z - b.z; }); if ((topWindow.z >= basis) && (windows[windows.length - 1] === topWindow)) { return; @@ -122,33 +127,22 @@ FocusScope { return lastTargetZ; } - function raiseWindow(item) { - var targetWindow = getDesktopWindow(item); - if (!targetWindow) { - console.warn("Could not find top level window for " + item); - return; - } - - if (!desktop) { - console.warn("Could not find desktop for window " + targetWindow); - return; - } - + function raiseWindow(targetWindow) { var predicate; var zBasis; if (isModalWindow(targetWindow)) { predicate = isModalWindow; - zBasis = zBasisModal + zBasis = zLevels.modal } else if (isAlwaysOnTopWindow(targetWindow)) { predicate = function(window) { return (isAlwaysOnTopWindow(window) && !isModalWindow(window)); } - zBasis = zBasisAlwaysOnTop + zBasis = zLevels.top } else { predicate = function(window) { return (!isAlwaysOnTopWindow(window) && !isModalWindow(window)); } - zBasis = zBasisNormal + zBasis = zLevels.normal } var windows = getTopLevelWindows(predicate); @@ -157,11 +151,64 @@ FocusScope { } function raise(item) { - d.raiseWindow(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) { + 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); } @@ -232,8 +279,6 @@ FocusScope { z: 9999; visible: false; color: "red" ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 } } - - } diff --git a/interface/resources/qml/js/Utils.js b/interface/resources/qml/js/Utils.js new file mode 100644 index 0000000000..417c8c1641 --- /dev/null +++ b/interface/resources/qml/js/Utils.js @@ -0,0 +1,16 @@ + +function clamp(value, min, max) { + return Math.min(Math.max(value, min), max); +} + +function clampVector(value, min, max) { + return Qt.vector2d( + clamp(value.x, min.x, max.x), + clamp(value.y, min.y, max.y)) +} + +function randomPosition(min, max) { + return Qt.vector2d( + Math.random() * (max.x - min.x), + Math.random() * (max.y - min.y)); +} diff --git a/interface/resources/qml/menus/MenuMouseHandler.qml b/interface/resources/qml/menus/MenuMouseHandler.qml index d22b30e8d9..bb2cc7d459 100644 --- a/interface/resources/qml/menus/MenuMouseHandler.qml +++ b/interface/resources/qml/menus/MenuMouseHandler.qml @@ -5,7 +5,6 @@ import "." Item { id: root - property int zBasis: 9000 anchors.fill: parent MouseArea { @@ -94,7 +93,7 @@ Item { function buildMenu(items, targetPosition) { var model = toModel(items); // Menu's must be childed to desktop for Z-ordering - var newMenu = menuViewMaker.createObject(desktop, { model: model, z: topMenu ? topMenu.z + 1 : zBasis }); + var newMenu = menuViewMaker.createObject(desktop, { model: model, z: topMenu ? topMenu.z + 1 : desktop.zLevels.menu }); if (targetPosition) { newMenu.x = targetPosition.x newMenu.y = targetPosition.y - newMenu.height / 3 * 1 diff --git a/interface/resources/qml/windows/Frame.qml b/interface/resources/qml/windows/Frame.qml index 4bcf3998f4..0ada0028e4 100644 --- a/interface/resources/qml/windows/Frame.qml +++ b/interface/resources/qml/windows/Frame.qml @@ -1,6 +1,7 @@ import QtQuick 2.5 import "../controls" +import "../js/Utils.js" as Utils Item { id: frame @@ -34,7 +35,7 @@ Item { function deltaSize(dx, dy) { var newSize = Qt.vector2d(window.width + dx, window.height + dy); - newSize = clampVector(newSize, window.minSize, window.maxSize); + newSize = Utils.clampVector(newSize, window.minSize, window.maxSize); window.width = newSize.x window.height = newSize.y } diff --git a/interface/resources/qml/windows/Window.qml b/interface/resources/qml/windows/Window.qml index 21bd8f3dec..8fe45f2227 100644 --- a/interface/resources/qml/windows/Window.qml +++ b/interface/resources/qml/windows/Window.qml @@ -19,6 +19,7 @@ Fadable { // decorations can extend outside it. implicitHeight: content.height implicitWidth: content.width + x: -1; y: -1 property int modality: Qt.NonModal @@ -71,15 +72,11 @@ Fadable { // frame styles, like a full desktop frame to simulate a modal window property var frame: DefaultFrame { } - Component.onCompleted: raise(); children: [ frame, content, activator ] - Component.onDestruction: { - content.destroy(); - console.log("Destroyed " + window); - windowDestroyed(); - } + Component.onCompleted: raise(); + Component.onDestruction: windowDestroyed(); onParentChanged: raise(); onVisibleChanged: { @@ -96,9 +93,6 @@ Fadable { function raise() { if (visible && parent) { desktop.raise(window) - if (!focus) { - focus = true; - } } } @@ -118,15 +112,15 @@ Fadable { visible = false; } - function clamp(value, min, max) { - return Math.min(Math.max(value, min), max); + function framedRect() { + if (!frame || !frame.decoration) { + return Qt.rect(0, 0, window.width, window.height) + } + return Qt.rect(frame.decoration.anchors.leftMargin, frame.decoration.anchors.topMargin, + window.width - frame.decoration.anchors.leftMargin - frame.decoration.anchors.rightMargin, + window.height - frame.decoration.anchors.topMargin - frame.decoration.anchors.bottomMargin) } - function clampVector(value, min, max) { - return Qt.vector2d( - clamp(value.x, min.x, max.x), - clamp(value.y, min.y, max.y)) - } Keys.onPressed: { switch(event.key) { diff --git a/tests/ui/qml/main.qml b/tests/ui/qml/main.qml index b343d2404e..c970cd711b 100644 --- a/tests/ui/qml/main.qml +++ b/tests/ui/qml/main.qml @@ -7,7 +7,6 @@ import "../../../interface/resources/qml" import "../../../interface/resources/qml/windows" import "../../../interface/resources/qml/dialogs" import "../../../interface/resources/qml/hifi" -import "../../../interface/resources/qml/hifi/dialogs" ApplicationWindow { id: appWindow @@ -184,6 +183,7 @@ ApplicationWindow { Window { id: yellow + objectName: "Yellow" closable: true visible: true resizable: true From 5fc43e7018d1a2b1bad6d6947da9cdb5567dc6f3 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 12:41:30 -0800 Subject: [PATCH 5/9] Render scalable favicons at a fixed size --- interface/resources/qml/Browser.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 39042a4046..32515d82b7 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -78,6 +78,7 @@ Window { source: webview.icon; x: (parent.height - height) / 2 y: (parent.width - width) / 2 + sourceSize: Qt.size(width, height); verticalAlignment: Image.AlignVCenter; horizontalAlignment: Image.AlignHCenter onSourceChanged: console.log("Icon url: " + source) From 12cc873716c8ee0e8ee3bd461c279b75a8e2882d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 12:43:33 -0800 Subject: [PATCH 6/9] Hide focus debugger unless it's explicitly turned on --- interface/resources/qml/desktop/Desktop.qml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index cf6c22b8fd..618d3825db 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -264,9 +264,8 @@ FocusScope { function onWindowFocusChanged() { console.log("Focus item is " + offscreenWindow.activeFocusItem); var focusedItem = offscreenWindow.activeFocusItem ; - if (DebugQML && focusedItem && false) { + if (DebugQML && focusedItem) { var rect = desktop.mapFromItem(focusedItem, 0, 0, focusedItem.width, focusedItem.height); - focusDebugger.visible = true focusDebugger.x = rect.x; focusDebugger.y = rect.y; focusDebugger.width = rect.width @@ -279,6 +278,13 @@ FocusScope { 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 + } } From 8e57f06de2d682fdb1fe07c3c99d3021329879aa Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 12:44:20 -0800 Subject: [PATCH 7/9] Add browser action shortcut to our custom desktop --- interface/resources/qml/hifi/Desktop.qml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 1655a32989..9d527c697a 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -1,4 +1,5 @@ import QtQuick 2.5 +import QtQuick.Controls 1.4 import "../desktop" import ".." @@ -9,6 +10,19 @@ Desktop { // The tool window, one instance property alias toolWindow: toolWindow ToolWindow { id: toolWindow } + + Action { + text: "Open Browser" + shortcut: "Ctrl+B" + onTriggered: { + console.log("Open browser"); + browserBuilder.createObject(desktop); + } + property var browserBuilder: Component { + Browser{} + } + } + } From a8433316267b740891b396b2ab58453fd7d91d09 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 17:19:03 -0800 Subject: [PATCH 8/9] Still trying to kill OSX warning --- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1807a45cc7..0ccd6a74bd 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -185,10 +185,10 @@ void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) { } using BackgroundPair = std::pair; -const std::array BACKGROUND_MODES = { +const std::array BACKGROUND_MODES = { { BackgroundPair { BACKGROUND_MODE_INHERIT, { "inherit" } }, BackgroundPair { BACKGROUND_MODE_SKYBOX, { "skybox" } } -}; +} }; QString EntityItemProperties::getBackgroundModeAsString() const { return BACKGROUND_MODES[_backgroundMode].second; From 3a0f6993c7968ac845547a9ff50351a1b47e2247 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 19:18:23 -0800 Subject: [PATCH 9/9] Put QML in front of 2D overlays --- interface/src/ui/ApplicationOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 43966553de..636b67f83f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -87,8 +87,8 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line renderAudioScope(renderArgs); // audio scope in the very back - NOTE: this is the debug audio scope, not the VU meter renderRearView(renderArgs); // renders the mirror view selfie - renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope + renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts renderStatsAndLogs(renderArgs); // currently renders nothing });