on xenial help sign in
Tell qtmir/miral about the available desktop area

So that it can make correct window management decisions Plus some refactorings: - Make AvailableDesktopArea provide boundariesForWindowPlacement - AvailableDesktopArea also replaces Stage.leftMargin and Panel.panelHeight in Stage.qml Approved by: Michael Zanetti, Unity8 CI Bot

commitd52069a1af3100f06f917c4dc7e99038a177a9e1 authorDaniel d'Andrada <daniel.dandrada@canonical.com> dateTue 28 Mar 2017, 21:46 (10 years ago) parent4141b11b4dc54f
14 files changed+338−57
plugins/WindowManager/AvailableDesktopArea.cpp+50 plugins/WindowManager/AvailableDesktopArea.h+38 plugins/WindowManager/CMakeLists.txt+7 plugins/WindowManager/WindowManagerPlugin.cpp+5−1 plugins/WindowManager/WindowMargins.cpp+74 plugins/WindowManager/WindowMargins.h+59 qml/Shell.qml+8−1 qml/Stage/ChildWindow.qml+8−1 qml/Stage/ChildWindowTree.qml+1 qml/Stage/DecoratedWindow.qml+14−7 qml/Stage/Stage.qml+57−47 tests/qmltests/Stage/tst_DesktopStage.qml+7 tests/qmltests/Stage/tst_PhoneStage.qml+5 tests/qmltests/Stage/tst_TabletStage.qml+5
plugins/WindowManager/AvailableDesktopArea.cppnew file+50
@@ -0,0 +1,50 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "AvailableDesktopArea.h"
18+
19+#include <QGuiApplication>
20+#include <QQuickWindow>
21+#include <qpa/qplatformnativeinterface.h>
22+
23+AvailableDesktopArea::AvailableDesktopArea(QQuickItem *parent)
24+ : QQuickItem(parent)
25+{
26+ connect(this, &QQuickItem::xChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
27+ connect(this, &QQuickItem::yChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
28+ connect(this, &QQuickItem::widthChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
29+ connect(this, &QQuickItem::heightChanged, this, &AvailableDesktopArea::updatePlatformWindowProperty);
30+}
31+
32+void AvailableDesktopArea::updatePlatformWindowProperty()
33+{
34+ if (!window()) {
35+ return;
36+ }
37+
38+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
39+
40+ QRect rect(x(), y(), width(), height());
41+
42+ nativeInterface->setWindowProperty(window()->handle(), "availableDesktopArea", QVariant(rect));
43+}
44+
45+void AvailableDesktopArea::itemChange(ItemChange change, const ItemChangeData &)
46+{
47+ if (change == ItemSceneChange) {
48+ updatePlatformWindowProperty();
49+ }
50+}
plugins/WindowManager/AvailableDesktopArea.hnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef AVAILABLEDESKTOPAREA_H
18+#define AVAILABLEDESKTOPAREA_H
19+
20+#include <QQuickItem>
21+
22+/**
23+ @brief Used to inform qtmir/miral about the available desktop area of shell
24+
25+ So that qtmir/miral can take correct window management decisions.
26+ */
27+class AvailableDesktopArea : public QQuickItem
28+{
29+ Q_OBJECT
30+public:
31+ AvailableDesktopArea(QQuickItem *parent = nullptr);
32+protected:
33+ void itemChange(ItemChange change, const ItemChangeData &value) override;
34+private Q_SLOTS:
35+ void updatePlatformWindowProperty();
36+};
37+
38+#endif // AVAILABLEDESKTOPAREA_H
plugins/WindowManager/CMakeLists.txt+7
@@ -1,7 +1,9 @@
11set(WINDOWMANAGER_SRC
2+ AvailableDesktopArea.cpp
23 TopLevelWindowModel.cpp
34 Window.cpp
45 WindowManagerPlugin.cpp
6+ WindowMargins.cpp
57 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
68 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
79 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
@@ -11,6 +13,11 @@ set(WINDOWMANAGER_SRC
1113
1214add_definitions(-DWINDOWMANAGERQML_LIBRARY)
1315
16+include_directories(
17+ SYSTEM
18+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
19+)
20+
1421add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC})
1522
1623qt5_use_modules(windowmanager-qml Qml Quick Gui)
plugins/WindowManager/WindowManagerPlugin.cpp+5−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-2017 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -16,14 +16,18 @@
1616
1717#include "WindowManagerPlugin.h"
1818
19+#include "AvailableDesktopArea.h"
1920#include "TopLevelWindowModel.h"
2021#include "Window.h"
22+#include "WindowMargins.h"
2123
2224#include <QtQml>
2325
2426void WindowManagerPlugin::registerTypes(const char *uri)
2527{
28+ qmlRegisterType<AvailableDesktopArea>(uri, 1, 0, "AvailableDesktopArea");
2629 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
30+ qmlRegisterType<WindowMargins>(uri, 1, 0, "WindowMargins");
2731
2832 qRegisterMetaType<Window*>("Window*");
2933
plugins/WindowManager/WindowMargins.cppnew file+74
@@ -0,0 +1,74 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "WindowMargins.h"
18+
19+#include <QGuiApplication>
20+#include <QQuickWindow>
21+#include <qpa/qplatformnativeinterface.h>
22+
23+void WindowMargins::setNormal(QRectF value)
24+{
25+ if (m_normal == value) {
26+ return;
27+ }
28+
29+ m_normal = value;
30+
31+ if (window()) {
32+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
33+ nativeInterface->setWindowProperty(window()->handle(), "normalWindowMargins", QVariant(m_normal.toRect()));
34+ }
35+
36+ Q_EMIT normalChanged();
37+}
38+
39+QRectF WindowMargins::normal() const
40+{
41+ return m_normal;
42+}
43+
44+void WindowMargins::setDialog(QRectF value)
45+{
46+ if (m_dialog == value) {
47+ return;
48+ }
49+
50+ m_dialog = value;
51+
52+ if (window()) {
53+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
54+ nativeInterface->setWindowProperty(window()->handle(), "dialogWindowMargins", QVariant(m_dialog.toRect()));
55+ }
56+
57+ Q_EMIT dialogChanged();
58+}
59+
60+QRectF WindowMargins::dialog() const
61+{
62+ return m_dialog;
63+}
64+
65+void WindowMargins::itemChange(ItemChange change, const ItemChangeData &data)
66+{
67+ if (change == ItemSceneChange && data.window != nullptr) {
68+ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
69+ if (!m_normal.isNull()) {
70+ nativeInterface->setWindowProperty(data.window->handle(), "normalWindowMargins", QVariant(m_normal.toRect()));
71+ nativeInterface->setWindowProperty(data.window->handle(), "dialogWindowMargins", QVariant(m_dialog.toRect()));
72+ }
73+ }
74+}
plugins/WindowManager/WindowMargins.hnew file+59
@@ -0,0 +1,59 @@
1+/*
2+ * Copyright (C) 2017 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef WINDOWMARGINS_H
18+#define WINDOWMARGINS_H
19+
20+#include <QQuickItem>
21+#include <QRectF>
22+
23+/*
24+ * Specifies window margins for different Mir window types
25+ *
26+ * Used to inform MirAL so that it can take window management decisions that match
27+ * the visuals drawn by Unity.
28+ */
29+class WindowMargins : public QQuickItem
30+{
31+ Q_OBJECT
32+
33+ // Margins for windows of normal type
34+ Q_PROPERTY(QRectF normal READ normal WRITE setNormal NOTIFY normalChanged)
35+
36+ // Margins for windows of dialog type
37+ Q_PROPERTY(QRectF dialog READ dialog WRITE setDialog NOTIFY dialogChanged)
38+
39+ // TODO: Add margins for other window types as needed
40+
41+public:
42+ QRectF normal() const;
43+ void setNormal(QRectF value);
44+
45+ QRectF dialog() const;
46+ void setDialog(QRectF value);
47+
48+protected:
49+ void itemChange(ItemChange change, const ItemChangeData &value) override;
50+
51+Q_SIGNALS:
52+ void normalChanged();
53+ void dialogChanged();
54+private:
55+ QRectF m_normal;
56+ QRectF m_dialog;
57+};
58+
59+#endif // WINDOWMARGINS_H
qml/Shell.qml+8−1
@@ -255,6 +255,13 @@ StyledItem {
255255 }
256256 }
257257
258+ AvailableDesktopArea {
259+ id: availableDesktopAreaItem
260+ anchors.fill: parent
261+ anchors.topMargin: panel.fullscreenMode ? 0 : panel.minimizedPanelHeight
262+ anchors.leftMargin: launcher.lockedVisible ? launcher.panelWidth : 0
263+ }
264+
258265 GSettings {
259266 id: settings
260267 schema.id: "com.canonical.Unity8"
@@ -290,6 +297,7 @@ StyledItem {
290297 topLevelSurfaceList: topLevelSurfaceList
291298 inputMethodRect: inputMethod.visibleRect
292299 rightEdgePushProgress: rightEdgeBarrier.progress
300+ availableDesktopArea: availableDesktopAreaItem
293301
294302 property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
295303 ? "phone"
@@ -311,7 +319,6 @@ StyledItem {
311319
312320 onInteractiveChanged: { if (interactive) { focus = true; } }
313321
314− leftMargin: shell.usageScenario == "desktop" && !settings.autohideLauncher ? launcher.panelWidth: 0
315322 suspended: greeter.shown
316323 altTabPressed: physicalKeysMapper.altTabPressed
317324 oskEnabled: shell.oskEnabled
qml/Stage/ChildWindow.qml+8−1
@@ -28,6 +28,7 @@ FocusScope {
2828 property Item target
2929 property alias requestedWidth: surfaceContainer.requestedWidth
3030 property alias requestedHeight: surfaceContainer.requestedHeight
31+ property real decorationHeight
3132
3233 width: surface ? surface.size.width : 0
3334 height: surface ? surface.size.height : 0
@@ -99,7 +100,8 @@ FocusScope {
99100
100101 sourceComponent: Component {
101102 WindowDecoration {
102− height: units.gu(3)
103+ id: windowDecoration
104+ height: root.decorationHeight
103105 title: root.surface ? root.surface.name : ""
104106 active: root.surface ? root.surface.focused : false
105107 closeButtonVisible: root.surface ? root.surface.type === Mir.SatelliteType
@@ -115,6 +117,11 @@ FocusScope {
115117 }
116118 onReleased: if (d.moveHandler) { d.moveHandler.handleReleased(); }
117119 onCloseClicked: root.surface.close();
120+ Binding {
121+ target: root.surface
122+ property: "topMargin"
123+ value: windowDecoration.height
124+ }
118125 }
119126 }
120127 }
qml/Stage/ChildWindowTree.qml+1
@@ -25,6 +25,7 @@ FocusScope {
2525 property real displacementX: 0
2626 property real displacementY: 0
2727 property alias boundsItem: childWindow.boundsItem
28+ property alias decorationHeight: childWindow.decorationHeight
2829
2930 x: surface ? surface.position.x + displacementX : 0
3031 y: surface ? surface.position.y + displacementY : 0
qml/Stage/DecoratedWindow.qml+14−7
@@ -43,6 +43,7 @@ FocusScope {
4343 property bool hasDecoration: true
4444 // This will temporarily show/hide the decoration without actually changing the surface's dimensions
4545 property real showDecoration: 1
46+ property alias decorationHeight: decoration.height
4647 property bool animateDecoration: false
4748 property bool showHighlight: false
4849 property int highlightSize: units.gu(1)
@@ -55,11 +56,15 @@ FocusScope {
5556 property int scaleToPreviewSize: units.gu(30)
5657
5758 property alias surfaceOrientationAngle: applicationWindow.surfaceOrientationAngle
58− readonly property real decorationHeight: Math.min(d.visibleDecorationHeight, d.requestedDecorationHeight)
59+
60+ // Height of the decoration that's actually being displayed at this moment. Will match decorationHeight
61+ // when the decoration is being fully displayed
62+ readonly property real actualDecorationHeight: Math.min(d.visibleDecorationHeight, d.requestedDecorationHeight)
63+
5964 readonly property bool counterRotate: surfaceOrientationAngle != 0 && surfaceOrientationAngle != 180
6065
6166 readonly property int minimumWidth: !counterRotate ? applicationWindow.minimumWidth : applicationWindow.minimumHeight
62− readonly property int minimumHeight: decorationHeight + (!counterRotate ? applicationWindow.minimumHeight : applicationWindow.minimumWidth)
67+ readonly property int minimumHeight: actualDecorationHeight + (!counterRotate ? applicationWindow.minimumHeight : applicationWindow.minimumWidth)
6368 readonly property int maximumWidth: !counterRotate ? applicationWindow.maximumWidth : applicationWindow.maximumHeight
6469 readonly property int maximumHeight: (root.decorationShown && applicationWindow.maximumHeight > 0 ? decoration.height : 0)
6570 + (!counterRotate ? applicationWindow.maximumHeight : applicationWindow.maximumWidth)
@@ -74,6 +79,8 @@ FocusScope {
7479
7580 property alias altDragEnabled: altDragHandler.enabled
7681
82+ property Item windowMargins
83+
7784 signal closeClicked()
7885 signal maximizeClicked()
7986 signal maximizeHorizontallyClicked()
@@ -102,7 +109,7 @@ FocusScope {
102109 PropertyChanges {
103110 target: root
104111 implicitWidth: counterRotate ? applicationWindow.implicitHeight : applicationWindow.implicitWidth
105− implicitHeight: root.decorationHeight + (counterRotate ? applicationWindow.implicitWidth: applicationWindow.implicitHeight)
112+ implicitHeight: root.actualDecorationHeight + (counterRotate ? applicationWindow.implicitWidth: applicationWindow.implicitHeight)
106113 }
107114 },
108115 State {
@@ -111,7 +118,7 @@ FocusScope {
111118 PropertyChanges {
112119 target: root
113120 implicitWidth: counterRotate ? applicationWindow.requestedHeight : applicationWindow.requestedWidth
114− implicitHeight: root.decorationHeight + (counterRotate ? applicationWindow.requestedWidth: applicationWindow.requestedHeight)
121+ implicitHeight: root.actualDecorationHeight + (counterRotate ? applicationWindow.requestedWidth: applicationWindow.requestedHeight)
115122 }
116123 },
117124 State {
@@ -150,7 +157,7 @@ FocusScope {
150157 margins: active ? -units.gu(2) : -units.gu(1.5)
151158 }
152159 height: Math.min(applicationWindow.implicitHeight, applicationWindow.height) * applicationWindow.itemScale
153− + root.decorationHeight * Math.min(1, root.showDecoration) + (active ? units.gu(4) : units.gu(3))
160+ + root.actualDecorationHeight * Math.min(1, root.showDecoration) + (active ? units.gu(4) : units.gu(3))
154161 source: "../graphics/dropshadow2gu.sci"
155162 opacity: root.shadowOpacity
156163 }
@@ -159,7 +166,7 @@ FocusScope {
159166 id: applicationWindow
160167 objectName: "appWindow"
161168 anchors.top: parent.top
162− anchors.topMargin: root.decorationHeight * Math.min(1, root.showDecoration)
169+ anchors.topMargin: root.actualDecorationHeight * Math.min(1, root.showDecoration)
163170 anchors.left: parent.left
164171 width: implicitWidth
165172 height: implicitHeight
@@ -207,7 +214,7 @@ FocusScope {
207214 objectName: "appWindowDecoration"
208215
209216 anchors { left: parent.left; top: parent.top; right: parent.right }
210− height: units.gu(3)
217+ height: units.gu(3) // a default value. overwritten by root.decorationHeight
211218
212219 title: applicationWindow.title
213220 windowMoving: moveHandler.moving && !altDragHandler.dragging
qml/Stage/Stage.qml+57−47
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
2+ * Copyright (C) 2014-2017 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@ import GlobalShortcut 1.0
2525import GSettings 1.0
2626import "Spread"
2727import "Spread/MathUtils.js" as MathUtils
28+import WindowManager 1.0
2829
2930FocusScope {
3031 id: root
@@ -43,10 +44,10 @@ FocusScope {
4344 property int shellOrientationAngle
4445 property bool spreadEnabled: true // If false, animations and right edge will be disabled
4546 property bool suspended
46− property int leftMargin: 0
4747 property bool oskEnabled: false
4848 property rect inputMethodRect
4949 property real rightEdgePushProgress: 0
50+ property Item availableDesktopArea
5051
5152 // Configuration
5253 property string mode: "staged"
@@ -120,6 +121,12 @@ FocusScope {
120121 }
121122 }
122123
124+ // For MirAL window management
125+ WindowMargins {
126+ normal: Qt.rect(0, root.mode === "windowed" ? priv.windowDecorationHeight : 0, 0, 0)
127+ dialog: normal
128+ }
129+
123130 property Item itemConfiningMouseCursor: !spreadShown && priv.focusedAppDelegate && priv.focusedAppDelegate.window.confinesMousePointer ?
124131 priv.focusedAppDelegate.clientAreaItem : null;
125132
@@ -367,6 +374,8 @@ FocusScope {
367374 }
368375
369376 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
377+
378+ readonly property real windowDecorationHeight: units.gu(3)
370379 }
371380
372381 Component.onCompleted: priv.updateMainAndSideStageIndexes();
@@ -587,7 +596,7 @@ FocusScope {
587596 id: spreadItem
588597 objectName: "spreadItem"
589598 anchors.fill: appContainer
590− leftMargin: root.leftMargin
599+ leftMargin: root.availableDesktopArea.x
591600 model: root.topLevelSurfaceList
592601 spreadFlickable: floatingFlickable
593602 z: 10
@@ -695,13 +704,6 @@ FocusScope {
695704 }
696705 }
697706
698− Item {
699− id: boundariesForWindowPlacement
700− anchors.fill: parent
701− anchors.topMargin: PanelState.panelHeight
702− visible: false
703− }
704−
705707 Repeater {
706708 id: appRepeater
707709 model: topLevelSurfaceList
@@ -799,7 +801,7 @@ FocusScope {
799801 target: appDelegate
800802 property: "y"
801803 value: appDelegate.requestedY -
802− Math.min(appDelegate.requestedY - PanelState.panelHeight,
804+ Math.min(appDelegate.requestedY - root.availableDesktopArea.y,
803805 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
804806 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
805807 && root.inputMethodRect.height > 0
@@ -817,8 +819,8 @@ FocusScope {
817819 angleDiff = (360 + angleDiff) % 360;
818820 if (angleDiff === 90 || angleDiff === 270) {
819821 var aux = decoratedWindow.requestedHeight;
820− decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.decorationHeight;
821− decoratedWindow.requestedWidth = aux - decoratedWindow.decorationHeight;
822+ decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.actualDecorationHeight;
823+ decoratedWindow.requestedWidth = aux - decoratedWindow.actualDecorationHeight;
822824 }
823825 }
824826 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
@@ -934,8 +936,8 @@ FocusScope {
934936 target: appDelegate
935937 screenWidth: appContainer.width
936938 screenHeight: appContainer.height
937− leftMargin: root.leftMargin
938− minimumY: boundariesForWindowPlacement.y
939+ leftMargin: root.availableDesktopArea.x
940+ minimumY: root.availableDesktopArea.y
939941 }
940942
941943 Connections {
@@ -1187,7 +1189,7 @@ FocusScope {
11871189
11881190 StagedRightEdgeMaths {
11891191 id: stagedRightEdgeMaths
1190− sceneWidth: appContainer.width - root.leftMargin
1192+ sceneWidth: root.availableDesktopArea.width
11911193 sceneHeight: appContainer.height
11921194 isMainStageApp: priv.mainStageDelegate == appDelegate
11931195 isSideStageApp: priv.sideStageDelegate == appDelegate
@@ -1198,7 +1200,7 @@ FocusScope {
11981200 progress: 0
11991201 targetHeight: spreadItem.stackHeight
12001202 targetX: spreadMaths.targetX
1201− startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1203+ startY: appDelegate.fullscreen ? 0 : root.availableDesktopArea.y
12021204 targetY: spreadMaths.targetY
12031205 targetAngle: spreadMaths.targetAngle
12041206 targetScale: spreadMaths.targetScale
@@ -1319,9 +1321,9 @@ FocusScope {
13191321 PropertyChanges {
13201322 target: appDelegate
13211323 x: stageMaths.itemX
1322− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1324+ y: root.availableDesktopArea.y
13231325 requestedWidth: appContainer.width
1324− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1326+ requestedHeight: root.availableDesktopArea.height
13251327 visuallyMaximized: true
13261328 visible: appDelegate.x < root.width
13271329 }
@@ -1351,10 +1353,10 @@ FocusScope {
13511353 PropertyChanges {
13521354 target: appDelegate
13531355 x: stageMaths.itemX
1354− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1356+ y: root.availableDesktopArea.y
13551357 z: stageMaths.itemZ
13561358 requestedWidth: stageMaths.itemWidth
1357− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1359+ requestedHeight: root.availableDesktopArea.height
13581360 visuallyMaximized: true
13591361 visible: appDelegate.x < root.width
13601362 }
@@ -1375,11 +1377,11 @@ FocusScope {
13751377 name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
13761378 PropertyChanges {
13771379 target: appDelegate;
1378− requestedX: root.leftMargin;
1380+ requestedX: root.availableDesktopArea.x;
13791381 requestedY: 0;
13801382 visuallyMinimized: false;
13811383 visuallyMaximized: true
1382− requestedWidth: appContainer.width - root.leftMargin;
1384+ requestedWidth: root.availableDesktopArea.width;
13831385 requestedHeight: appContainer.height;
13841386 }
13851387 PropertyChanges { target: touchControls; enabled: true }
@@ -1423,10 +1425,10 @@ FocusScope {
14231425 extend: "normal"
14241426 PropertyChanges {
14251427 target: appDelegate
1426− windowedX: root.leftMargin
1427− windowedY: PanelState.panelHeight
1428− windowedWidth: (appContainer.width - root.leftMargin)/2
1429− windowedHeight: appContainer.height - PanelState.panelHeight
1428+ windowedX: root.availableDesktopArea.x
1429+ windowedY: root.availableDesktopArea.y
1430+ windowedWidth: root.availableDesktopArea.width / 2
1431+ windowedHeight: root.availableDesktopArea.height
14301432 }
14311433 },
14321434 State {
@@ -1434,7 +1436,7 @@ FocusScope {
14341436 extend: "maximizedLeft"
14351437 PropertyChanges {
14361438 target: appDelegate;
1437− windowedX: (appContainer.width + root.leftMargin)/2
1439+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14381440 }
14391441 },
14401442 State {
@@ -1442,10 +1444,10 @@ FocusScope {
14421444 extend: "normal"
14431445 PropertyChanges {
14441446 target: appDelegate
1445− windowedX: root.leftMargin
1446− windowedY: PanelState.panelHeight
1447− windowedWidth: (appContainer.width - root.leftMargin)/2
1448− windowedHeight: (appContainer.height - PanelState.panelHeight)/2
1447+ windowedX: root.availableDesktopArea.x
1448+ windowedY: root.availableDesktopArea.y
1449+ windowedWidth: root.availableDesktopArea.width / 2
1450+ windowedHeight: root.availableDesktopArea.height / 2
14491451 }
14501452 },
14511453 State {
@@ -1453,7 +1455,7 @@ FocusScope {
14531455 extend: "maximizedTopLeft"
14541456 PropertyChanges {
14551457 target: appDelegate
1456− windowedX: (appContainer.width + root.leftMargin)/2
1458+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14571459 }
14581460 },
14591461 State {
@@ -1461,10 +1463,10 @@ FocusScope {
14611463 extend: "normal"
14621464 PropertyChanges {
14631465 target: appDelegate
1464− windowedX: root.leftMargin
1465− windowedY: (appContainer.height + PanelState.panelHeight)/2
1466− windowedWidth: (appContainer.width - root.leftMargin)/2
1467− windowedHeight: appContainer.height/2
1466+ windowedX: root.availableDesktopArea.x
1467+ windowedY: root.availableDesktopArea.y + (root.availableDesktopArea.height / 2)
1468+ windowedWidth: root.availableDesktopArea.width / 2
1469+ windowedHeight: root.availableDesktopArea.height / 2
14681470 }
14691471 },
14701472 State {
@@ -1472,20 +1474,26 @@ FocusScope {
14721474 extend: "maximizedBottomLeft"
14731475 PropertyChanges {
14741476 target: appDelegate
1475− windowedX: (appContainer.width + root.leftMargin)/2
1477+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14761478 }
14771479 },
14781480 State {
14791481 name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
14801482 extend: "normal"
1481− PropertyChanges { target: appDelegate; windowedX: root.leftMargin; windowedY: windowedY;
1482− windowedWidth: appContainer.width - root.leftMargin; windowedHeight: windowedHeight }
1483+ PropertyChanges {
1484+ target: appDelegate
1485+ windowedX: root.availableDesktopArea.x; windowedY: windowedY
1486+ windowedWidth: root.availableDesktopArea.width; windowedHeight: windowedHeight
1487+ }
14831488 },
14841489 State {
14851490 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
14861491 extend: "normal"
1487− PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: PanelState.panelHeight;
1488− windowedWidth: windowedWidth; windowedHeight: appContainer.height - PanelState.panelHeight }
1492+ PropertyChanges {
1493+ target: appDelegate
1494+ windowedX: windowedX; windowedY: root.availableDesktopArea.y
1495+ windowedWidth: windowedWidth; windowedHeight: root.availableDesktopArea.height
1496+ }
14891497 },
14901498 State {
14911499 name: "minimized"; when: appDelegate.minimized
@@ -1613,7 +1621,7 @@ FocusScope {
16131621 anchors.margins: touchControls.overlayShown ? borderThickness/2 : -borderThickness
16141622
16151623 target: appDelegate
1616− boundsItem: boundariesForWindowPlacement
1624+ boundsItem: root.availableDesktopArea
16171625 minWidth: units.gu(10)
16181626 minHeight: units.gu(10)
16191627 borderThickness: units.gu(2)
@@ -1636,13 +1644,14 @@ FocusScope {
16361644 focus: true
16371645 interactive: root.interactive
16381646 showDecoration: 1
1647+ decorationHeight: priv.windowDecorationHeight
16391648 maximizeButtonShown: appDelegate.canBeMaximized
16401649 overlayShown: touchControls.overlayShown
16411650 width: implicitWidth
16421651 height: implicitHeight
16431652 highlightSize: windowInfoItem.iconMargin / 2
1644− boundsItem: boundariesForWindowPlacement
16451653 altDragEnabled: root.mode == "windowed"
1654+ boundsItem: root.availableDesktopArea
16461655
16471656 requestedWidth: appDelegate.requestedWidth
16481657 requestedHeight: appDelegate.requestedHeight
@@ -1705,7 +1714,7 @@ FocusScope {
17051714 resizeArea: resizeArea
17061715 enabled: false
17071716 visible: enabled
1708− boundsItem: boundariesForWindowPlacement
1717+ boundsItem: root.availableDesktopArea
17091718
17101719 onFakeMaximizeAnimationRequested: if (!appDelegate.maximized) fakeRectangle.maximize(amount, true)
17111720 onFakeMaximizeLeftAnimationRequested: if (!appDelegate.maximizedLeft) fakeRectangle.maximizeLeft(amount, true)
@@ -1826,7 +1835,8 @@ FocusScope {
18261835 displacementX: appDelegate.clientAreaItem.x
18271836 displacementY: appDelegate.clientAreaItem.y
18281837
1829− boundsItem: boundariesForWindowPlacement
1838+ boundsItem: root.availableDesktopArea
1839+ decorationHeight: priv.windowDecorationHeight
18301840
18311841 z: childWindowRepeater.count - model.index
18321842
@@ -1847,7 +1857,7 @@ FocusScope {
18471857 FakeMaximizeDelegate {
18481858 id: fakeRectangle
18491859 target: priv.focusedAppDelegate
1850− leftMargin: root.leftMargin
1860+ leftMargin: root.availableDesktopArea.x
18511861 appContainerWidth: appContainer.width
18521862 appContainerHeight: appContainer.height
18531863 }
tests/qmltests/Stage/tst_DesktopStage.qml+7
@@ -100,8 +100,15 @@ Item {
100100 orientations: Orientations {}
101101 applicationManager: ApplicationManager
102102 topLevelSurfaceList: topSurfaceList
103+ availableDesktopArea: availableDesktopAreaItem
103104 interactive: true
104105 mode: "windowed"
106+
107+ Item {
108+ id: availableDesktopAreaItem
109+ anchors.fill: parent
110+ anchors.topMargin: PanelState.panelHeight
111+ }
105112 }
106113 }
107114 }
tests/qmltests/Stage/tst_PhoneStage.qml+5
@@ -52,6 +52,11 @@ Item {
5252 applicationManager: ApplicationManager
5353 surfaceManager: sMgr
5454 }
55+ availableDesktopArea: availableDesktopAreaItem
56+ Item {
57+ id: availableDesktopAreaItem
58+ anchors.fill: parent
59+ }
5560 Component.onCompleted: {
5661 ApplicationManager.startApplication("unity8-dash");
5762 }
tests/qmltests/Stage/tst_TabletStage.qml+5
@@ -61,6 +61,11 @@ Rectangle {
6161 applicationManager: ApplicationManager
6262 surfaceManager: sMgr
6363 }
64+ availableDesktopArea: availableDesktopAreaItem
65+ Item {
66+ id: availableDesktopAreaItem
67+ anchors.fill: parent
68+ }
6469 Component.onCompleted: {
6570 ApplicationManager.startApplication("unity8-dash");
6671 }