on xenial help sign in
Tell qtmir/miral about the available desktop area
b4dc54fDaniel d'Andrada
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 @@
1set(WINDOWMANAGER_SRC
1set(WINDOWMANAGER_SRC
2+ AvailableDesktopArea.cpp
2 TopLevelWindowModel.cpp
3 TopLevelWindowModel.cpp
3 Window.cpp
4 Window.cpp
4 WindowManagerPlugin.cpp
5 WindowManagerPlugin.cpp
6+ WindowMargins.cpp
5 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
7 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
6 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
8 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
7 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
9 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
@@ -11,6 +13,11 @@ set(WINDOWMANAGER_SRC
11
13
12add_definitions(-DWINDOWMANAGERQML_LIBRARY)
14add_definitions(-DWINDOWMANAGERQML_LIBRARY)
13
15
16+include_directories(
17+ SYSTEM
18+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
19+)
20+
14add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC})
21add_library(windowmanager-qml SHARED ${WINDOWMANAGER_SRC})
15
22
16qt5_use_modules(windowmanager-qml Qml Quick Gui)
23qt5_use_modules(windowmanager-qml Qml Quick Gui)
plugins/WindowManager/WindowManagerPlugin.cpp+5−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2016-2017 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -16,14 +16,18 @@
16
16
17#include "WindowManagerPlugin.h"
17#include "WindowManagerPlugin.h"
18
18
19+#include "AvailableDesktopArea.h"
19#include "TopLevelWindowModel.h"
20#include "TopLevelWindowModel.h"
20#include "Window.h"
21#include "Window.h"
22+#include "WindowMargins.h"
21
23
22#include <QtQml>
24#include <QtQml>
23
25
24void WindowManagerPlugin::registerTypes(const char *uri)
26void WindowManagerPlugin::registerTypes(const char *uri)
25{
27{
28+ qmlRegisterType<AvailableDesktopArea>(uri, 1, 0, "AvailableDesktopArea");
26 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
29 qmlRegisterType<TopLevelWindowModel>(uri, 1, 0, "TopLevelWindowModel");
30+ qmlRegisterType<WindowMargins>(uri, 1, 0, "WindowMargins");
27
31
28 qRegisterMetaType<Window*>("Window*");
32 qRegisterMetaType<Window*>("Window*");
29
33
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 {
255 }
255 }
256 }
256 }
257
257
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+
258 GSettings {
265 GSettings {
259 id: settings
266 id: settings
260 schema.id: "com.canonical.Unity8"
267 schema.id: "com.canonical.Unity8"
@@ -290,6 +297,7 @@ StyledItem {
290 topLevelSurfaceList: topLevelSurfaceList
297 topLevelSurfaceList: topLevelSurfaceList
291 inputMethodRect: inputMethod.visibleRect
298 inputMethodRect: inputMethod.visibleRect
292 rightEdgePushProgress: rightEdgeBarrier.progress
299 rightEdgePushProgress: rightEdgeBarrier.progress
300+ availableDesktopArea: availableDesktopAreaItem
293
301
294 property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
302 property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
295 ? "phone"
303 ? "phone"
@@ -311,7 +319,6 @@ StyledItem {
311
319
312 onInteractiveChanged: { if (interactive) { focus = true; } }
320 onInteractiveChanged: { if (interactive) { focus = true; } }
313
321
314− leftMargin: shell.usageScenario == "desktop" && !settings.autohideLauncher ? launcher.panelWidth: 0
315 suspended: greeter.shown
322 suspended: greeter.shown
316 altTabPressed: physicalKeysMapper.altTabPressed
323 altTabPressed: physicalKeysMapper.altTabPressed
317 oskEnabled: shell.oskEnabled
324 oskEnabled: shell.oskEnabled
qml/Stage/ChildWindow.qml+8−1
@@ -28,6 +28,7 @@ FocusScope {
28 property Item target
28 property Item target
29 property alias requestedWidth: surfaceContainer.requestedWidth
29 property alias requestedWidth: surfaceContainer.requestedWidth
30 property alias requestedHeight: surfaceContainer.requestedHeight
30 property alias requestedHeight: surfaceContainer.requestedHeight
31+ property real decorationHeight
31
32
32 width: surface ? surface.size.width : 0
33 width: surface ? surface.size.width : 0
33 height: surface ? surface.size.height : 0
34 height: surface ? surface.size.height : 0
@@ -99,7 +100,8 @@ FocusScope {
99
100
100 sourceComponent: Component {
101 sourceComponent: Component {
101 WindowDecoration {
102 WindowDecoration {
102− height: units.gu(3)
103+ id: windowDecoration
104+ height: root.decorationHeight
103 title: root.surface ? root.surface.name : ""
105 title: root.surface ? root.surface.name : ""
104 active: root.surface ? root.surface.focused : false
106 active: root.surface ? root.surface.focused : false
105 closeButtonVisible: root.surface ? root.surface.type === Mir.SatelliteType
107 closeButtonVisible: root.surface ? root.surface.type === Mir.SatelliteType
@@ -115,6 +117,11 @@ FocusScope {
115 }
117 }
116 onReleased: if (d.moveHandler) { d.moveHandler.handleReleased(); }
118 onReleased: if (d.moveHandler) { d.moveHandler.handleReleased(); }
117 onCloseClicked: root.surface.close();
119 onCloseClicked: root.surface.close();
120+ Binding {
121+ target: root.surface
122+ property: "topMargin"
123+ value: windowDecoration.height
124+ }
118 }
125 }
119 }
126 }
120 }
127 }
qml/Stage/ChildWindowTree.qml+1
@@ -25,6 +25,7 @@ FocusScope {
25 property real displacementX: 0
25 property real displacementX: 0
26 property real displacementY: 0
26 property real displacementY: 0
27 property alias boundsItem: childWindow.boundsItem
27 property alias boundsItem: childWindow.boundsItem
28+ property alias decorationHeight: childWindow.decorationHeight
28
29
29 x: surface ? surface.position.x + displacementX : 0
30 x: surface ? surface.position.x + displacementX : 0
30 y: surface ? surface.position.y + displacementY : 0
31 y: surface ? surface.position.y + displacementY : 0
qml/Stage/DecoratedWindow.qml+14−7
@@ -43,6 +43,7 @@ FocusScope {
43 property bool hasDecoration: true
43 property bool hasDecoration: true
44 // This will temporarily show/hide the decoration without actually changing the surface's dimensions
44 // This will temporarily show/hide the decoration without actually changing the surface's dimensions
45 property real showDecoration: 1
45 property real showDecoration: 1
46+ property alias decorationHeight: decoration.height
46 property bool animateDecoration: false
47 property bool animateDecoration: false
47 property bool showHighlight: false
48 property bool showHighlight: false
48 property int highlightSize: units.gu(1)
49 property int highlightSize: units.gu(1)
@@ -55,11 +56,15 @@ FocusScope {
55 property int scaleToPreviewSize: units.gu(30)
56 property int scaleToPreviewSize: units.gu(30)
56
57
57 property alias surfaceOrientationAngle: applicationWindow.surfaceOrientationAngle
58 property alias surfaceOrientationAngle: applicationWindow.surfaceOrientationAngle
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
58− readonly property real decorationHeight: Math.min(d.visibleDecorationHeight, d.requestedDecorationHeight)
62+ readonly property real actualDecorationHeight: Math.min(d.visibleDecorationHeight, d.requestedDecorationHeight)
63+
59 readonly property bool counterRotate: surfaceOrientationAngle != 0 && surfaceOrientationAngle != 180
64 readonly property bool counterRotate: surfaceOrientationAngle != 0 && surfaceOrientationAngle != 180
60
65
61 readonly property int minimumWidth: !counterRotate ? applicationWindow.minimumWidth : applicationWindow.minimumHeight
66 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)
63 readonly property int maximumWidth: !counterRotate ? applicationWindow.maximumWidth : applicationWindow.maximumHeight
68 readonly property int maximumWidth: !counterRotate ? applicationWindow.maximumWidth : applicationWindow.maximumHeight
64 readonly property int maximumHeight: (root.decorationShown && applicationWindow.maximumHeight > 0 ? decoration.height : 0)
69 readonly property int maximumHeight: (root.decorationShown && applicationWindow.maximumHeight > 0 ? decoration.height : 0)
65 + (!counterRotate ? applicationWindow.maximumHeight : applicationWindow.maximumWidth)
70 + (!counterRotate ? applicationWindow.maximumHeight : applicationWindow.maximumWidth)
@@ -74,6 +79,8 @@ FocusScope {
74
79
75 property alias altDragEnabled: altDragHandler.enabled
80 property alias altDragEnabled: altDragHandler.enabled
76
81
82+ property Item windowMargins
83+
77 signal closeClicked()
84 signal closeClicked()
78 signal maximizeClicked()
85 signal maximizeClicked()
79 signal maximizeHorizontallyClicked()
86 signal maximizeHorizontallyClicked()
@@ -102,7 +109,7 @@ FocusScope {
102 PropertyChanges {
109 PropertyChanges {
103 target: root
110 target: root
104 implicitWidth: counterRotate ? applicationWindow.implicitHeight : applicationWindow.implicitWidth
111 implicitWidth: counterRotate ? applicationWindow.implicitHeight : applicationWindow.implicitWidth
105− implicitHeight: root.decorationHeight + (counterRotate ? applicationWindow.implicitWidth: applicationWindow.implicitHeight)
112+ implicitHeight: root.actualDecorationHeight + (counterRotate ? applicationWindow.implicitWidth: applicationWindow.implicitHeight)
106 }
113 }
107 },
114 },
108 State {
115 State {
@@ -111,7 +118,7 @@ FocusScope {
111 PropertyChanges {
118 PropertyChanges {
112 target: root
119 target: root
113 implicitWidth: counterRotate ? applicationWindow.requestedHeight : applicationWindow.requestedWidth
120 implicitWidth: counterRotate ? applicationWindow.requestedHeight : applicationWindow.requestedWidth
114− implicitHeight: root.decorationHeight + (counterRotate ? applicationWindow.requestedWidth: applicationWindow.requestedHeight)
121+ implicitHeight: root.actualDecorationHeight + (counterRotate ? applicationWindow.requestedWidth: applicationWindow.requestedHeight)
115 }
122 }
116 },
123 },
117 State {
124 State {
@@ -150,7 +157,7 @@ FocusScope {
150 margins: active ? -units.gu(2) : -units.gu(1.5)
157 margins: active ? -units.gu(2) : -units.gu(1.5)
151 }
158 }
152 height: Math.min(applicationWindow.implicitHeight, applicationWindow.height) * applicationWindow.itemScale
159 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))
154 source: "../graphics/dropshadow2gu.sci"
161 source: "../graphics/dropshadow2gu.sci"
155 opacity: root.shadowOpacity
162 opacity: root.shadowOpacity
156 }
163 }
@@ -159,7 +166,7 @@ FocusScope {
159 id: applicationWindow
166 id: applicationWindow
160 objectName: "appWindow"
167 objectName: "appWindow"
161 anchors.top: parent.top
168 anchors.top: parent.top
162− anchors.topMargin: root.decorationHeight * Math.min(1, root.showDecoration)
169+ anchors.topMargin: root.actualDecorationHeight * Math.min(1, root.showDecoration)
163 anchors.left: parent.left
170 anchors.left: parent.left
164 width: implicitWidth
171 width: implicitWidth
165 height: implicitHeight
172 height: implicitHeight
@@ -207,7 +214,7 @@ FocusScope {
207 objectName: "appWindowDecoration"
214 objectName: "appWindowDecoration"
208
215
209 anchors { left: parent.left; top: parent.top; right: parent.right }
216 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
211
218
212 title: applicationWindow.title
219 title: applicationWindow.title
213 windowMoving: moveHandler.moving && !altDragHandler.dragging
220 windowMoving: moveHandler.moving && !altDragHandler.dragging
qml/Stage/Stage.qml+57−47
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
2+ * Copyright (C) 2014-2017 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@ import GlobalShortcut 1.0
25import GSettings 1.0
25import GSettings 1.0
26import "Spread"
26import "Spread"
27import "Spread/MathUtils.js" as MathUtils
27import "Spread/MathUtils.js" as MathUtils
28+import WindowManager 1.0
28
29
29FocusScope {
30FocusScope {
30 id: root
31 id: root
@@ -43,10 +44,10 @@ FocusScope {
43 property int shellOrientationAngle
44 property int shellOrientationAngle
44 property bool spreadEnabled: true // If false, animations and right edge will be disabled
45 property bool spreadEnabled: true // If false, animations and right edge will be disabled
45 property bool suspended
46 property bool suspended
46− property int leftMargin: 0
47 property bool oskEnabled: false
47 property bool oskEnabled: false
48 property rect inputMethodRect
48 property rect inputMethodRect
49 property real rightEdgePushProgress: 0
49 property real rightEdgePushProgress: 0
50+ property Item availableDesktopArea
50
51
51 // Configuration
52 // Configuration
52 property string mode: "staged"
53 property string mode: "staged"
@@ -120,6 +121,12 @@ FocusScope {
120 }
121 }
121 }
122 }
122
123
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+
123 property Item itemConfiningMouseCursor: !spreadShown && priv.focusedAppDelegate && priv.focusedAppDelegate.window.confinesMousePointer ?
130 property Item itemConfiningMouseCursor: !spreadShown && priv.focusedAppDelegate && priv.focusedAppDelegate.window.confinesMousePointer ?
124 priv.focusedAppDelegate.clientAreaItem : null;
131 priv.focusedAppDelegate.clientAreaItem : null;
125
132
@@ -347,6 +354,8 @@ FocusScope {
347 }
354 }
348
355
349 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
356 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
357+
358+ readonly property real windowDecorationHeight: units.gu(3)
350 }
359 }
351
360
352 Component.onCompleted: priv.updateMainAndSideStageIndexes();
361 Component.onCompleted: priv.updateMainAndSideStageIndexes();
@@ -567,7 +576,7 @@ FocusScope {
567 id: spreadItem
576 id: spreadItem
568 objectName: "spreadItem"
577 objectName: "spreadItem"
569 anchors.fill: appContainer
578 anchors.fill: appContainer
570− leftMargin: root.leftMargin
579+ leftMargin: root.availableDesktopArea.x
571 model: root.topLevelSurfaceList
580 model: root.topLevelSurfaceList
572 spreadFlickable: floatingFlickable
581 spreadFlickable: floatingFlickable
573 z: 10
582 z: 10
@@ -675,13 +684,6 @@ FocusScope {
675 }
684 }
676 }
685 }
677
686
678− Item {
679− id: boundariesForWindowPlacement
680− anchors.fill: parent
681− anchors.topMargin: PanelState.panelHeight
682− visible: false
683− }
684−
685 Repeater {
687 Repeater {
686 id: appRepeater
688 id: appRepeater
687 model: topLevelSurfaceList
689 model: topLevelSurfaceList
@@ -779,7 +781,7 @@ FocusScope {
779 target: appDelegate
781 target: appDelegate
780 property: "y"
782 property: "y"
781 value: appDelegate.requestedY -
783 value: appDelegate.requestedY -
782− Math.min(appDelegate.requestedY - PanelState.panelHeight,
784+ Math.min(appDelegate.requestedY - root.availableDesktopArea.y,
783 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
785 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
784 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
786 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
785 && root.inputMethodRect.height > 0
787 && root.inputMethodRect.height > 0
@@ -797,8 +799,8 @@ FocusScope {
797 angleDiff = (360 + angleDiff) % 360;
799 angleDiff = (360 + angleDiff) % 360;
798 if (angleDiff === 90 || angleDiff === 270) {
800 if (angleDiff === 90 || angleDiff === 270) {
799 var aux = decoratedWindow.requestedHeight;
801 var aux = decoratedWindow.requestedHeight;
800− decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.decorationHeight;
802+ decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.actualDecorationHeight;
801− decoratedWindow.requestedWidth = aux - decoratedWindow.decorationHeight;
803+ decoratedWindow.requestedWidth = aux - decoratedWindow.actualDecorationHeight;
802 }
804 }
803 }
805 }
804 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
806 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
@@ -914,8 +916,8 @@ FocusScope {
914 target: appDelegate
916 target: appDelegate
915 screenWidth: appContainer.width
917 screenWidth: appContainer.width
916 screenHeight: appContainer.height
918 screenHeight: appContainer.height
917− leftMargin: root.leftMargin
919+ leftMargin: root.availableDesktopArea.x
918− minimumY: boundariesForWindowPlacement.y
920+ minimumY: root.availableDesktopArea.y
919 }
921 }
920
922
921 Connections {
923 Connections {
@@ -1167,7 +1169,7 @@ FocusScope {
1167
1169
1168 StagedRightEdgeMaths {
1170 StagedRightEdgeMaths {
1169 id: stagedRightEdgeMaths
1171 id: stagedRightEdgeMaths
1170− sceneWidth: appContainer.width - root.leftMargin
1172+ sceneWidth: root.availableDesktopArea.width
1171 sceneHeight: appContainer.height
1173 sceneHeight: appContainer.height
1172 isMainStageApp: priv.mainStageDelegate == appDelegate
1174 isMainStageApp: priv.mainStageDelegate == appDelegate
1173 isSideStageApp: priv.sideStageDelegate == appDelegate
1175 isSideStageApp: priv.sideStageDelegate == appDelegate
@@ -1178,7 +1180,7 @@ FocusScope {
1178 progress: 0
1180 progress: 0
1179 targetHeight: spreadItem.stackHeight
1181 targetHeight: spreadItem.stackHeight
1180 targetX: spreadMaths.targetX
1182 targetX: spreadMaths.targetX
1181− startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1183+ startY: appDelegate.fullscreen ? 0 : root.availableDesktopArea.y
1182 targetY: spreadMaths.targetY
1184 targetY: spreadMaths.targetY
1183 targetAngle: spreadMaths.targetAngle
1185 targetAngle: spreadMaths.targetAngle
1184 targetScale: spreadMaths.targetScale
1186 targetScale: spreadMaths.targetScale
@@ -1299,9 +1301,9 @@ FocusScope {
1299 PropertyChanges {
1301 PropertyChanges {
1300 target: appDelegate
1302 target: appDelegate
1301 x: stageMaths.itemX
1303 x: stageMaths.itemX
1302− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1304+ y: root.availableDesktopArea.y
1303 requestedWidth: appContainer.width
1305 requestedWidth: appContainer.width
1304− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1306+ requestedHeight: root.availableDesktopArea.height
1305 visuallyMaximized: true
1307 visuallyMaximized: true
1306 visible: appDelegate.x < root.width
1308 visible: appDelegate.x < root.width
1307 }
1309 }
@@ -1331,10 +1333,10 @@ FocusScope {
1331 PropertyChanges {
1333 PropertyChanges {
1332 target: appDelegate
1334 target: appDelegate
1333 x: stageMaths.itemX
1335 x: stageMaths.itemX
1334− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1336+ y: root.availableDesktopArea.y
1335 z: stageMaths.itemZ
1337 z: stageMaths.itemZ
1336 requestedWidth: stageMaths.itemWidth
1338 requestedWidth: stageMaths.itemWidth
1337− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1339+ requestedHeight: root.availableDesktopArea.height
1338 visuallyMaximized: true
1340 visuallyMaximized: true
1339 visible: appDelegate.x < root.width
1341 visible: appDelegate.x < root.width
1340 }
1342 }
@@ -1355,11 +1357,11 @@ FocusScope {
1355 name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
1357 name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
1356 PropertyChanges {
1358 PropertyChanges {
1357 target: appDelegate;
1359 target: appDelegate;
1358− requestedX: root.leftMargin;
1360+ requestedX: root.availableDesktopArea.x;
1359 requestedY: 0;
1361 requestedY: 0;
1360 visuallyMinimized: false;
1362 visuallyMinimized: false;
1361 visuallyMaximized: true
1363 visuallyMaximized: true
1362− requestedWidth: appContainer.width - root.leftMargin;
1364+ requestedWidth: root.availableDesktopArea.width;
1363 requestedHeight: appContainer.height;
1365 requestedHeight: appContainer.height;
1364 }
1366 }
1365 PropertyChanges { target: touchControls; enabled: true }
1367 PropertyChanges { target: touchControls; enabled: true }
@@ -1402,10 +1404,10 @@ FocusScope {
1402 extend: "normal"
1404 extend: "normal"
1403 PropertyChanges {
1405 PropertyChanges {
1404 target: appDelegate
1406 target: appDelegate
1405− windowedX: root.leftMargin
1407+ windowedX: root.availableDesktopArea.x
1406− windowedY: PanelState.panelHeight
1408+ windowedY: root.availableDesktopArea.y
1407− windowedWidth: (appContainer.width - root.leftMargin)/2
1409+ windowedWidth: root.availableDesktopArea.width / 2
1408− windowedHeight: appContainer.height - PanelState.panelHeight
1410+ windowedHeight: root.availableDesktopArea.height
1409 }
1411 }
1410 },
1412 },
1411 State {
1413 State {
@@ -1413,7 +1415,7 @@ FocusScope {
1413 extend: "maximizedLeft"
1415 extend: "maximizedLeft"
1414 PropertyChanges {
1416 PropertyChanges {
1415 target: appDelegate;
1417 target: appDelegate;
1416− windowedX: (appContainer.width + root.leftMargin)/2
1418+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
1417 }
1419 }
1418 },
1420 },
1419 State {
1421 State {
@@ -1421,10 +1423,10 @@ FocusScope {
1421 extend: "normal"
1423 extend: "normal"
1422 PropertyChanges {
1424 PropertyChanges {
1423 target: appDelegate
1425 target: appDelegate
1424− windowedX: root.leftMargin
1426+ windowedX: root.availableDesktopArea.x
1425− windowedY: PanelState.panelHeight
1427+ windowedY: root.availableDesktopArea.y
1426− windowedWidth: (appContainer.width - root.leftMargin)/2
1428+ windowedWidth: root.availableDesktopArea.width / 2
1427− windowedHeight: (appContainer.height - PanelState.panelHeight)/2
1429+ windowedHeight: root.availableDesktopArea.height / 2
1428 }
1430 }
1429 },
1431 },
1430 State {
1432 State {
@@ -1432,7 +1434,7 @@ FocusScope {
1432 extend: "maximizedTopLeft"
1434 extend: "maximizedTopLeft"
1433 PropertyChanges {
1435 PropertyChanges {
1434 target: appDelegate
1436 target: appDelegate
1435− windowedX: (appContainer.width + root.leftMargin)/2
1437+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
1436 }
1438 }
1437 },
1439 },
1438 State {
1440 State {
@@ -1440,10 +1442,10 @@ FocusScope {
1440 extend: "normal"
1442 extend: "normal"
1441 PropertyChanges {
1443 PropertyChanges {
1442 target: appDelegate
1444 target: appDelegate
1443− windowedX: root.leftMargin
1445+ windowedX: root.availableDesktopArea.x
1444− windowedY: (appContainer.height + PanelState.panelHeight)/2
1446+ windowedY: root.availableDesktopArea.y + (root.availableDesktopArea.height / 2)
1445− windowedWidth: (appContainer.width - root.leftMargin)/2
1447+ windowedWidth: root.availableDesktopArea.width / 2
1446− windowedHeight: appContainer.height/2
1448+ windowedHeight: root.availableDesktopArea.height / 2
1447 }
1449 }
1448 },
1450 },
1449 State {
1451 State {
@@ -1451,20 +1453,26 @@ FocusScope {
1451 extend: "maximizedBottomLeft"
1453 extend: "maximizedBottomLeft"
1452 PropertyChanges {
1454 PropertyChanges {
1453 target: appDelegate
1455 target: appDelegate
1454− windowedX: (appContainer.width + root.leftMargin)/2
1456+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
1455 }
1457 }
1456 },
1458 },
1457 State {
1459 State {
1458 name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
1460 name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
1459 extend: "normal"
1461 extend: "normal"
1462+ PropertyChanges {
1463+ target: appDelegate
1460− PropertyChanges { target: appDelegate; windowedX: root.leftMargin; windowedY: windowedY;
1464+ windowedX: root.availableDesktopArea.x; windowedY: windowedY
1461− windowedWidth: appContainer.width - root.leftMargin; windowedHeight: windowedHeight }
1465+ windowedWidth: root.availableDesktopArea.width; windowedHeight: windowedHeight
1466+ }
1462 },
1467 },
1463 State {
1468 State {
1464 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
1469 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
1465 extend: "normal"
1470 extend: "normal"
1471+ PropertyChanges {
1472+ target: appDelegate
1466− PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: PanelState.panelHeight;
1473+ windowedX: windowedX; windowedY: root.availableDesktopArea.y
1467− windowedWidth: windowedWidth; windowedHeight: appContainer.height - PanelState.panelHeight }
1474+ windowedWidth: windowedWidth; windowedHeight: root.availableDesktopArea.height
1475+ }
1468 },
1476 },
1469 State {
1477 State {
1470 name: "minimized"; when: appDelegate.minimized
1478 name: "minimized"; when: appDelegate.minimized
@@ -1592,7 +1600,7 @@ FocusScope {
1592 anchors.margins: touchControls.overlayShown ? borderThickness/2 : -borderThickness
1600 anchors.margins: touchControls.overlayShown ? borderThickness/2 : -borderThickness
1593
1601
1594 target: appDelegate
1602 target: appDelegate
1595− boundsItem: boundariesForWindowPlacement
1603+ boundsItem: root.availableDesktopArea
1596 minWidth: units.gu(10)
1604 minWidth: units.gu(10)
1597 minHeight: units.gu(10)
1605 minHeight: units.gu(10)
1598 borderThickness: units.gu(2)
1606 borderThickness: units.gu(2)
@@ -1615,13 +1623,14 @@ FocusScope {
1615 focus: true
1623 focus: true
1616 interactive: root.interactive
1624 interactive: root.interactive
1617 showDecoration: 1
1625 showDecoration: 1
1626+ decorationHeight: priv.windowDecorationHeight
1618 maximizeButtonShown: appDelegate.canBeMaximized
1627 maximizeButtonShown: appDelegate.canBeMaximized
1619 overlayShown: touchControls.overlayShown
1628 overlayShown: touchControls.overlayShown
1620 width: implicitWidth
1629 width: implicitWidth
1621 height: implicitHeight
1630 height: implicitHeight
1622 highlightSize: windowInfoItem.iconMargin / 2
1631 highlightSize: windowInfoItem.iconMargin / 2
1623− boundsItem: boundariesForWindowPlacement
1624 altDragEnabled: root.mode == "windowed"
1632 altDragEnabled: root.mode == "windowed"
1633+ boundsItem: root.availableDesktopArea
1625
1634
1626 requestedWidth: appDelegate.requestedWidth
1635 requestedWidth: appDelegate.requestedWidth
1627 requestedHeight: appDelegate.requestedHeight
1636 requestedHeight: appDelegate.requestedHeight
@@ -1684,7 +1693,7 @@ FocusScope {
1684 resizeArea: resizeArea
1693 resizeArea: resizeArea
1685 enabled: false
1694 enabled: false
1686 visible: enabled
1695 visible: enabled
1687− boundsItem: boundariesForWindowPlacement
1696+ boundsItem: root.availableDesktopArea
1688
1697
1689 onFakeMaximizeAnimationRequested: if (!appDelegate.maximized) fakeRectangle.maximize(amount, true)
1698 onFakeMaximizeAnimationRequested: if (!appDelegate.maximized) fakeRectangle.maximize(amount, true)
1690 onFakeMaximizeLeftAnimationRequested: if (!appDelegate.maximizedLeft) fakeRectangle.maximizeLeft(amount, true)
1699 onFakeMaximizeLeftAnimationRequested: if (!appDelegate.maximizedLeft) fakeRectangle.maximizeLeft(amount, true)
@@ -1805,7 +1814,8 @@ FocusScope {
1805 displacementX: appDelegate.clientAreaItem.x
1814 displacementX: appDelegate.clientAreaItem.x
1806 displacementY: appDelegate.clientAreaItem.y
1815 displacementY: appDelegate.clientAreaItem.y
1807
1816
1808− boundsItem: boundariesForWindowPlacement
1817+ boundsItem: root.availableDesktopArea
1818+ decorationHeight: priv.windowDecorationHeight
1809
1819
1810 z: childWindowRepeater.count - model.index
1820 z: childWindowRepeater.count - model.index
1811
1821
@@ -1826,7 +1836,7 @@ FocusScope {
1826 FakeMaximizeDelegate {
1836 FakeMaximizeDelegate {
1827 id: fakeRectangle
1837 id: fakeRectangle
1828 target: priv.focusedAppDelegate
1838 target: priv.focusedAppDelegate
1829− leftMargin: root.leftMargin
1839+ leftMargin: root.availableDesktopArea.x
1830 appContainerWidth: appContainer.width
1840 appContainerWidth: appContainer.width
1831 appContainerHeight: appContainer.height
1841 appContainerHeight: appContainer.height
1832 }
1842 }
tests/qmltests/Stage/tst_DesktopStage.qml+7
@@ -100,8 +100,15 @@ Item {
100 orientations: Orientations {}
100 orientations: Orientations {}
101 applicationManager: ApplicationManager
101 applicationManager: ApplicationManager
102 topLevelSurfaceList: topSurfaceList
102 topLevelSurfaceList: topSurfaceList
103+ availableDesktopArea: availableDesktopAreaItem
103 interactive: true
104 interactive: true
104 mode: "windowed"
105 mode: "windowed"
106+
107+ Item {
108+ id: availableDesktopAreaItem
109+ anchors.fill: parent
110+ anchors.topMargin: PanelState.panelHeight
111+ }
105 }
112 }
106 }
113 }
107 }
114 }
tests/qmltests/Stage/tst_PhoneStage.qml+5
@@ -52,6 +52,11 @@ Item {
52 applicationManager: ApplicationManager
52 applicationManager: ApplicationManager
53 surfaceManager: sMgr
53 surfaceManager: sMgr
54 }
54 }
55+ availableDesktopArea: availableDesktopAreaItem
56+ Item {
57+ id: availableDesktopAreaItem
58+ anchors.fill: parent
59+ }
55 Component.onCompleted: {
60 Component.onCompleted: {
56 ApplicationManager.startApplication("unity8-dash");
61 ApplicationManager.startApplication("unity8-dash");
57 }
62 }
tests/qmltests/Stage/tst_TabletStage.qml+5
@@ -61,6 +61,11 @@ Rectangle {
61 applicationManager: ApplicationManager
61 applicationManager: ApplicationManager
62 surfaceManager: sMgr
62 surfaceManager: sMgr
63 }
63 }
64+ availableDesktopArea: availableDesktopAreaItem
65+ Item {
66+ id: availableDesktopAreaItem
67+ anchors.fill: parent
68+ }
64 Component.onCompleted: {
69 Component.onCompleted: {
65 ApplicationManager.startApplication("unity8-dash");
70 ApplicationManager.startApplication("unity8-dash");
66 }
71 }