From 4ab7b660d44e3e6095a19d583575b56c3738d998 Mon Sep 17 00:00:00 2001
From: Brad Hefta-Gaub <brad@highfidelity.io>
Date: Mon, 25 Apr 2016 20:19:54 -0700
Subject: [PATCH] fix a bunch of bugs in qml window placement

---
 interface/resources/qml/AssetServer.qml       |  1 -
 interface/resources/qml/AvatarInputs.qml      |  2 +-
 interface/resources/qml/InfoView.qml          | 18 ++++
 interface/resources/qml/desktop/Desktop.qml   | 89 +++++++++++++++++--
 .../qml/hifi/dialogs/RunningScripts.qml       |  1 -
 .../resources/qml/windows-uit/Window.qml      | 16 +++-
 interface/resources/qml/windows/Window.qml    | 16 +++-
 interface/src/Application.cpp                 |  1 +
 libraries/plugins/src/plugins/DisplayPlugin.h |  3 +-
 9 files changed, 134 insertions(+), 13 deletions(-)

diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml
index 495d13d118..370bc92d81 100644
--- a/interface/resources/qml/AssetServer.qml
+++ b/interface/resources/qml/AssetServer.qml
@@ -24,7 +24,6 @@ Window {
     title: "Asset Browser"
     resizable: true
     destroyOnInvisible: true
-    x: 40; y: 40
     implicitWidth: 384; implicitHeight: 640
     minSize: Qt.vector2d(200, 300)
 
diff --git a/interface/resources/qml/AvatarInputs.qml b/interface/resources/qml/AvatarInputs.qml
index 75f379a425..4150979cd4 100644
--- a/interface/resources/qml/AvatarInputs.qml
+++ b/interface/resources/qml/AvatarInputs.qml
@@ -25,7 +25,7 @@ Hifi.AvatarInputs {
     readonly property int iconPadding: 5
 
     readonly property bool shouldReposition: true
-    
+
     Settings {
         category: "Overlay.AvatarInputs"
         property alias x: root.x
diff --git a/interface/resources/qml/InfoView.qml b/interface/resources/qml/InfoView.qml
index bc268baeb4..025cc6cc59 100644
--- a/interface/resources/qml/InfoView.qml
+++ b/interface/resources/qml/InfoView.qml
@@ -22,4 +22,22 @@ Windows.Window {
             url: infoView.url
         }
      }
+
+    Component.onCompleted: {
+        //console.log("InfoView.Component.onCompleted");
+        centerWindow(root);
+    }
+
+
+    onVisibleChanged: {
+        if (visible) {
+            centerWindow(root);
+        }
+    }
+
+    function centerWindow() {
+        //console.log("InfoView.Component.centerWindow");
+        desktop.centerOnVisible(root);
+    }
+
 }
diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml
index c0804a967d..2a2c6b5d24 100644
--- a/interface/resources/qml/desktop/Desktop.qml
+++ b/interface/resources/qml/desktop/Desktop.qml
@@ -21,7 +21,8 @@ FocusScope {
     objectName: "desktop"
     anchors.fill: parent
 
-    property rect recommendedRect: rect(0,0,0,0);
+    property rect recommendedRect: Qt.rect(0,0,0,0);
+    property var expectedChildren;
 
     onHeightChanged: d.handleSizeChanged();
     
@@ -55,14 +56,28 @@ FocusScope {
 
         function handleSizeChanged() {
             var oldRecommendedRect = recommendedRect;
-            var newRecommendedRectJS = Controller.getRecommendedOverlayRect();
+            var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
             var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, 
                                     newRecommendedRectJS.width, 
                                     newRecommendedRectJS.height);
 
-            if (oldRecommendedRect != Qt.rect(0,0,0,0)
-                  && oldRecommendedRect != newRecommendedRect) {
+            var oldChildren = expectedChildren;
+            var newChildren = d.getRepositionChildren();
+
+            //console.log("handleSizeChanged() - oldChildren:" + oldChildren);
+            //console.log("handleSizeChanged() - newChildren:" + newChildren);
+            //console.log("handleSizeChanged() - oldRecommendedRect:" + oldRecommendedRect);
+            //console.log("handleSizeChanged() - newRecommendedRect:" + newRecommendedRect);
+
+            if (oldRecommendedRect != Qt.rect(0,0,0,0) 
+                  && (oldRecommendedRect != newRecommendedRect
+                      || oldChildren != newChildren)
+                ) {
+                expectedChildren = newChildren;
+                //console.log("handleSizeChanged() - calling repositionAll()");
                 d.repositionAll();
+            } else {
+                //console.log("handleSizeChanged() - DID NOT CALL repositionAll()");
             }
             recommendedRect = newRecommendedRect;
         }
@@ -244,6 +259,7 @@ FocusScope {
             for (var i = 0; i < windows.length; ++i) {
                 var targetWindow = windows[i];
                 if (targetWindow.visible) {
+                    //console.log("repositionAll() about to repositionWindow() targetWindow:" + targetWindow);
                     repositionWindow(targetWindow, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
                 }
             }
@@ -252,6 +268,7 @@ FocusScope {
             var otherChildren = d.getRepositionChildren();
             for (var i = 0; i < otherChildren.length; ++i) {
                 var child = otherChildren[i];
+                //console.log("repositionAll() about to repositionWindow() child:" + child);
                 repositionWindow(child, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
             }
 
@@ -279,13 +296,66 @@ FocusScope {
             targetWindow.focus = true;
         }
 
+        showDesktop();
+    }
+
+    function centerOnVisible(item) {
+        //console.log("centerOnVisible() item:" + item);
+        var targetWindow = d.getDesktopWindow(item);
+        //console.log("centerOnVisible() targetWindow:" + targetWindow );
+        if (!targetWindow) {
+            console.warn("Could not find top level window for " + item);
+            return;
+        }
+
+        if (typeof Controller === "undefined") {
+            console.warn("Controller not yet available... can't center");
+            return;
+        }
+
+        var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
+        var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, 
+                                newRecommendedRectJS.width, 
+                                newRecommendedRectJS.height);
+        var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
+        var newX = newRecommendedRect.x + ((newRecommendedRect.width - targetWindow.width) / 2);
+        var newY = newRecommendedRect.y + ((newRecommendedRect.height - targetWindow.height) / 2);
+
+        //console.log("centerOnVisible() newRecommendedRect:" + newRecommendedRect.x + "," + newRecommendedRect.y + "/" + newRecommendedRect.width + "x" + newRecommendedRect.height);
+        //console.log("centerOnVisible() newX/newY:" + newX + "," + newY);
+
+        targetWindow.x = newX;
+        targetWindow.y = newY;
+
+        if (recommendedRect != newRecommendedRect) {
+            //console.log("centerOnVisible() -- detected new recommended rect");
+            //console.log("old recommendedRect:" + recommendedRect);
+            //console.log("newRecommendedRect:" + newRecommendedRect);
+            recommendedRect = newRecommendedRect;
+        }
+
+    }
+
+    function repositionOnVisible(item) {
+        console.warn("repositionOnVisible() item:" + item);
+        var targetWindow = d.getDesktopWindow(item);
+        console.warn("repositionOnVisible() targetWindow:" + targetWindow);
+        if (!targetWindow) {
+            console.warn("Could not find top level window for " + item);
+            return;
+        }
+
+        if (typeof Controller === "undefined") {
+            console.warn("Controller not yet available... can't reposition targetWindow:" + targetWindow);
+            return;
+        }
+
+
         var oldRecommendedRect = recommendedRect;
         var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
         var newRecommendedRect = Controller.getRecommendedOverlayRect();
         var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
         repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
-
-        showDesktop();
     }
 
     function repositionWindow(targetWindow, forceReposition, 
@@ -324,10 +394,15 @@ FocusScope {
             }
             var fractionX = Utils.clamp(originRelativeX / oldRecommendedDimmensions.x, 0, 1);
             var fractionY = Utils.clamp(originRelativeY / oldRecommendedDimmensions.y, 0, 1);
-
             var newX = (fractionX * newRecommendedDimmensions.x) + newRecommendedRect.x;
             var newY = (fractionY * newRecommendedDimmensions.y) + newRecommendedRect.y;
 
+            //console.log("repositionWindow() oldRecommendedRect:" + oldRecommendedRect.x + "," + oldRecommendedRect.y + "/" + oldRecommendedRect.width + "x" + oldRecommendedRect.height);
+            //console.log("repositionWindow() newRecommendedRect:" + newRecommendedRect.x + "," + newRecommendedRect.y + "/" + newRecommendedRect.width + "x" + newRecommendedRect.height);
+            //console.log("repositionWindow() originRelativeX/originRelativeY:" + originRelativeX + "," + originRelativeY);
+            //console.log("repositionWindow() fractionX/fractionY:" + fractionX + "," + fractionY);
+            //console.log("repositionWindow() newX/newY:" + newX + "," + newY);
+
             newPosition = Qt.vector2d(newX, newY);
         }
         targetWindow.x = newPosition.x;
diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml
index 9b35d55f11..071789fe16 100644
--- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml
+++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml
@@ -23,7 +23,6 @@ Window {
     title: "Running Scripts"
     resizable: true
     destroyOnInvisible: true
-    x: 40; y: 40
     implicitWidth: 400
     implicitHeight: isHMD ? 695 : 728
     minSize: Qt.vector2d(200, 300)
diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml
index dbbf2b3eb6..59d5dcd70e 100644
--- a/interface/resources/qml/windows-uit/Window.qml
+++ b/interface/resources/qml/windows-uit/Window.qml
@@ -31,7 +31,7 @@ Fadable {
     // decorations can extend outside it.
     implicitHeight: content ? content.height : 0
     implicitWidth: content ? content.width : 0
-    x: -1; y: -1
+    x: -9999; y: -9999
     enabled: visible
 
     signal windowDestroyed();
@@ -249,9 +249,11 @@ Fadable {
     children: [ swallower, frame, pane, activator ]
 
     Component.onCompleted: {
+        //console.log("Window(uit).Component.onCompleted window:" + window);
         window.parentChanged.connect(raise);
         raise();
         setDefaultFocus();
+        centerOrReposition();
     }
     Component.onDestruction: {
         window.parentChanged.disconnect(raise);  // Prevent warning on shutdown
@@ -267,6 +269,18 @@ Fadable {
             raise();
         }
         enabled = visible
+
+        if (visible && parent) {
+            centerOrReposition();
+        }
+    }
+
+    function centerOrReposition() {
+        if (x == -9999 && y == -9999) {
+            desktop.centerOnVisible(window);
+        } else {
+            desktop.repositionOnVisible(window);
+        }
     }
 
     function raise() {
diff --git a/interface/resources/qml/windows/Window.qml b/interface/resources/qml/windows/Window.qml
index 06be0cd9e7..c24f4a3b9b 100644
--- a/interface/resources/qml/windows/Window.qml
+++ b/interface/resources/qml/windows/Window.qml
@@ -19,7 +19,7 @@ Fadable {
     // decorations can extend outside it.
     implicitHeight: content ? content.height : 0
     implicitWidth: content ? content.width : 0
-    x: -1; y: -1
+    x: -9999; y: -9999
     enabled: visible
 
     signal windowDestroyed();
@@ -115,14 +115,24 @@ Fadable {
     children: [ swallower, frame, content, activator ]
 
     Component.onCompleted: {
+        //console.log("Window(uit).Component.onCompleted window:" + window);
         window.parentChanged.connect(raise);
         raise();
+        centerOrReposition();
     }
     Component.onDestruction: {
         window.parentChanged.disconnect(raise);  // Prevent warning on shutdown
         windowDestroyed();
     }
 
+    function centerOrReposition() {
+        if (x == -9999 && y == -9999) {
+            desktop.centerOnVisible(window);
+        } else {
+            desktop.repositionOnVisible(window);
+        }
+    }
+
     onVisibleChanged: {
         if (!visible && destroyOnInvisible) {
             destroy();
@@ -132,6 +142,10 @@ Fadable {
             raise();
         }
         enabled = visible
+
+        if (visible && parent) {
+            centerOrReposition();
+        }
     }
 
     function raise() {
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index fcf1425287..c2a4088dcc 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -4315,6 +4315,7 @@ void Application::nodeKilled(SharedNodePointer node) {
         }
     }
 }
+
 void Application::trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket) {
     // Attempt to identify the sender from its address.
     if (sendingNode) {
diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h
index 64a73ab12a..91dcf9398f 100644
--- a/libraries/plugins/src/plugins/DisplayPlugin.h
+++ b/libraries/plugins/src/plugins/DisplayPlugin.h
@@ -107,7 +107,8 @@ public:
 
     // The recommended bounds for primary overlay placement
     virtual QRect getRecommendedOverlayRect() const {
-        auto recommendedSize = getRecommendedUiSize();
+        const int DESKTOP_SCREEN_PADDING = 50;
+        auto recommendedSize = getRecommendedUiSize() - glm::uvec2(DESKTOP_SCREEN_PADDING);
         return QRect(0, 0, recommendedSize.x, recommendedSize.y);
     }