@@ -1,5 +1,5 @@
2− * Copyright (C) 2014-2016 Canonical, Ltd.
2+ * Copyright (C) 2014-2017 Canonical, Ltd.
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
29FocusScope {
30FocusScope {
@@ -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
51 // Configuration
52 // Configuration
52 property string mode: "staged"
53 property string mode: "staged"
@@ -120,6 +121,12 @@ FocusScope {
124+ // For MirAL window management
126+ normal: Qt.rect(0, root.mode === "windowed" ? priv.windowDecorationHeight : 0, 0, 0)
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;
@@ -224,10 +231,30 @@ FocusScope {
224 active: priv.focusedAppDelegate !== null
231 active: priv.focusedAppDelegate !== null
235+ shortcut: Qt.ControlModifier|Qt.AltModifier|Qt.Key_T
237+ // try in this order: snap pkg, new deb name, old deb name
238+ var candidates = ["ubuntu-terminal-app_ubuntu-terminal-app", "ubuntu-terminal-app", "com.ubuntu.terminal"];
239+ for (var i = 0; i < candidates.length; i++) {
240+ if (priv.startApp(candidates[i]))
227 QtObject {
246 QtObject {
229 objectName: "DesktopStagePrivate"
248 objectName: "DesktopStagePrivate"
250+ function startApp(appId) {
251+ if (root.applicationManager.findApplication(appId)) {
252+ return root.applicationManager.requestFocusApplication(appId);
254+ return root.applicationManager.startApplication(appId) !== null;
231 property var focusedAppDelegate: null
258 property var focusedAppDelegate: null
232 property var foregroundMaximizedAppDelegate: null // for stuff like drop shadow and focusing maximized app by clicking panel
259 property var foregroundMaximizedAppDelegate: null // for stuff like drop shadow and focusing maximized app by clicking panel
@@ -347,6 +374,8 @@ FocusScope {
349 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
376 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
378+ readonly property real windowDecorationHeight: units.gu(3)
352 Component.onCompleted: priv.updateMainAndSideStageIndexes();
381 Component.onCompleted: priv.updateMainAndSideStageIndexes();
@@ -568,7 +597,7 @@ FocusScope {
568 id: spreadItem
597 id: spreadItem
569 objectName: "spreadItem"
598 objectName: "spreadItem"
570 anchors.fill: appContainer
599 anchors.fill: appContainer
571− leftMargin: root.leftMargin
600+ leftMargin: root.availableDesktopArea.x
572 model: root.topLevelSurfaceList
601 model: root.topLevelSurfaceList
573 spreadFlickable: floatingFlickable
602 spreadFlickable: floatingFlickable
@@ -676,13 +705,6 @@ FocusScope {
680− id: boundariesForWindowPlacement
681− anchors.fill: parent
682− anchors.topMargin: PanelState.panelHeight
686 Repeater {
708 Repeater {
687 id: appRepeater
709 id: appRepeater
688 model: topLevelSurfaceList
710 model: topLevelSurfaceList
@@ -780,7 +802,7 @@ FocusScope {
780 target: appDelegate
802 target: appDelegate
781 property: "y"
803 property: "y"
782 value: appDelegate.requestedY -
804 value: appDelegate.requestedY -
783− Math.min(appDelegate.requestedY - PanelState.panelHeight,
805+ Math.min(appDelegate.requestedY - root.availableDesktopArea.y,
784 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
806 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
785 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
807 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
786 && root.inputMethodRect.height > 0
808 && root.inputMethodRect.height > 0
@@ -798,8 +820,8 @@ FocusScope {
798 angleDiff = (360 + angleDiff) % 360;
820 angleDiff = (360 + angleDiff) % 360;
799 if (angleDiff === 90 || angleDiff === 270) {
821 if (angleDiff === 90 || angleDiff === 270) {
800 var aux = decoratedWindow.requestedHeight;
822 var aux = decoratedWindow.requestedHeight;
801− decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.decorationHeight;
823+ decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.actualDecorationHeight;
802− decoratedWindow.requestedWidth = aux - decoratedWindow.decorationHeight;
824+ decoratedWindow.requestedWidth = aux - decoratedWindow.actualDecorationHeight;
805 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
827 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
@@ -900,12 +922,13 @@ FocusScope {
900 priv.updateMainAndSideStageIndexes();
922 priv.updateMainAndSideStageIndexes();
902 appDelegate.focus = true;
924 appDelegate.focus = true;
925+ priv.focusedAppDelegate = appDelegate;
905 function updateQmlFocusFromMirSurfaceFocus() {
928 function updateQmlFocusFromMirSurfaceFocus() {
906 if (model.window.focused) {
929 if (model.window.focused) {
907 claimFocus();
930 claimFocus();
908− priv.focusedAppDelegate = appDelegate;
931+ decoratedWindow.focus = true;
@@ -914,8 +937,8 @@ FocusScope {
914 target: appDelegate
937 target: appDelegate
915 screenWidth: appContainer.width
938 screenWidth: appContainer.width
916 screenHeight: appContainer.height
939 screenHeight: appContainer.height
917− leftMargin: root.leftMargin
940+ leftMargin: root.availableDesktopArea.x
918− minimumY: boundariesForWindowPlacement.y
941+ minimumY: root.availableDesktopArea.y
921 Connections {
944 Connections {
@@ -1167,7 +1190,7 @@ FocusScope {
1168 StagedRightEdgeMaths {
1191 StagedRightEdgeMaths {
1169 id: stagedRightEdgeMaths
1192 id: stagedRightEdgeMaths
1170− sceneWidth: appContainer.width - root.leftMargin
1193+ sceneWidth: root.availableDesktopArea.width
1171 sceneHeight: appContainer.height
1194 sceneHeight: appContainer.height
1172 isMainStageApp: priv.mainStageDelegate == appDelegate
1195 isMainStageApp: priv.mainStageDelegate == appDelegate
1173 isSideStageApp: priv.sideStageDelegate == appDelegate
1196 isSideStageApp: priv.sideStageDelegate == appDelegate
@@ -1178,7 +1201,7 @@ FocusScope {
1178 progress: 0
1201 progress: 0
1179 targetHeight: spreadItem.stackHeight
1202 targetHeight: spreadItem.stackHeight
1180 targetX: spreadMaths.targetX
1203 targetX: spreadMaths.targetX
1181− startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1204+ startY: appDelegate.fullscreen ? 0 : root.availableDesktopArea.y
1182 targetY: spreadMaths.targetY
1205 targetY: spreadMaths.targetY
1183 targetAngle: spreadMaths.targetAngle
1206 targetAngle: spreadMaths.targetAngle
1184 targetScale: spreadMaths.targetScale
1207 targetScale: spreadMaths.targetScale
@@ -1299,9 +1322,9 @@ FocusScope {
1299 PropertyChanges {
1322 PropertyChanges {
1300 target: appDelegate
1323 target: appDelegate
1301 x: stageMaths.itemX
1324 x: stageMaths.itemX
1302− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1325+ y: root.availableDesktopArea.y
1303 requestedWidth: appContainer.width
1326 requestedWidth: appContainer.width
1304− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1327+ requestedHeight: root.availableDesktopArea.height
1305 visuallyMaximized: true
1328 visuallyMaximized: true
1306 visible: appDelegate.x < root.width
1329 visible: appDelegate.x < root.width
@@ -1331,10 +1354,10 @@ FocusScope {
1331 PropertyChanges {
1354 PropertyChanges {
1332 target: appDelegate
1355 target: appDelegate
1333 x: stageMaths.itemX
1356 x: stageMaths.itemX
1334− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1357+ y: root.availableDesktopArea.y
1335 z: stageMaths.itemZ
1358 z: stageMaths.itemZ
1336 requestedWidth: stageMaths.itemWidth
1359 requestedWidth: stageMaths.itemWidth
1337− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1360+ requestedHeight: root.availableDesktopArea.height
1338 visuallyMaximized: true
1361 visuallyMaximized: true
1339 visible: appDelegate.x < root.width
1362 visible: appDelegate.x < root.width
@@ -1355,11 +1378,11 @@ FocusScope {
1355 name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
1378 name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
1356 PropertyChanges {
1379 PropertyChanges {
1357 target: appDelegate;
1380 target: appDelegate;
1358− requestedX: root.leftMargin;
1381+ requestedX: root.availableDesktopArea.x;
1359 requestedY: 0;
1382 requestedY: 0;
1360 visuallyMinimized: false;
1383 visuallyMinimized: false;
1361 visuallyMaximized: true
1384 visuallyMaximized: true
1362− requestedWidth: appContainer.width - root.leftMargin;
1385+ requestedWidth: root.availableDesktopArea.width;
1363 requestedHeight: appContainer.height;
1386 requestedHeight: appContainer.height;
1365 PropertyChanges { target: touchControls; enabled: true }
1388 PropertyChanges { target: touchControls; enabled: true }
@@ -1392,6 +1415,7 @@ FocusScope {
1392 when: appDelegate.windowState == WindowStateStorage.WindowStateRestored
1415 when: appDelegate.windowState == WindowStateStorage.WindowStateRestored
1393 extend: "normal"
1416 extend: "normal"
1394 PropertyChanges {
1417 PropertyChanges {
1418+ restoreEntryValues: false
1395 target: appDelegate;
1419 target: appDelegate;
1396 windowedX: restoredX;
1420 windowedX: restoredX;
1397 windowedY: restoredY;
1421 windowedY: restoredY;
@@ -1402,10 +1426,10 @@ FocusScope {
1402 extend: "normal"
1426 extend: "normal"
1403 PropertyChanges {
1427 PropertyChanges {
1404 target: appDelegate
1428 target: appDelegate
1405− windowedX: root.leftMargin
1429+ windowedX: root.availableDesktopArea.x
1406− windowedY: PanelState.panelHeight
1430+ windowedY: root.availableDesktopArea.y
1407− windowedWidth: (appContainer.width - root.leftMargin)/2
1431+ windowedWidth: root.availableDesktopArea.width / 2
1408− windowedHeight: appContainer.height - PanelState.panelHeight
1432+ windowedHeight: root.availableDesktopArea.height
@@ -1413,7 +1437,7 @@ FocusScope {
1413 extend: "maximizedLeft"
1437 extend: "maximizedLeft"
1414 PropertyChanges {
1438 PropertyChanges {
1415 target: appDelegate;
1439 target: appDelegate;
1416− windowedX: (appContainer.width + root.leftMargin)/2
1440+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
@@ -1421,10 +1445,10 @@ FocusScope {
1421 extend: "normal"
1445 extend: "normal"
1422 PropertyChanges {
1446 PropertyChanges {
1423 target: appDelegate
1447 target: appDelegate
1424− windowedX: root.leftMargin
1448+ windowedX: root.availableDesktopArea.x
1425− windowedY: PanelState.panelHeight
1449+ windowedY: root.availableDesktopArea.y
1426− windowedWidth: (appContainer.width - root.leftMargin)/2
1450+ windowedWidth: root.availableDesktopArea.width / 2
1427− windowedHeight: (appContainer.height - PanelState.panelHeight)/2
1451+ windowedHeight: root.availableDesktopArea.height / 2
@@ -1432,7 +1456,7 @@ FocusScope {
1432 extend: "maximizedTopLeft"
1456 extend: "maximizedTopLeft"
1433 PropertyChanges {
1457 PropertyChanges {
1434 target: appDelegate
1458 target: appDelegate
1435− windowedX: (appContainer.width + root.leftMargin)/2
1459+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
@@ -1440,10 +1464,10 @@ FocusScope {
1440 extend: "normal"
1464 extend: "normal"
1441 PropertyChanges {
1465 PropertyChanges {
1442 target: appDelegate
1466 target: appDelegate
1443− windowedX: root.leftMargin
1467+ windowedX: root.availableDesktopArea.x
1444− windowedY: (appContainer.height + PanelState.panelHeight)/2
1468+ windowedY: root.availableDesktopArea.y + (root.availableDesktopArea.height / 2)
1445− windowedWidth: (appContainer.width - root.leftMargin)/2
1469+ windowedWidth: root.availableDesktopArea.width / 2
1446− windowedHeight: appContainer.height/2
1470+ windowedHeight: root.availableDesktopArea.height / 2
@@ -1451,20 +1475,26 @@ FocusScope {
1451 extend: "maximizedBottomLeft"
1475 extend: "maximizedBottomLeft"
1452 PropertyChanges {
1476 PropertyChanges {
1453 target: appDelegate
1477 target: appDelegate
1454− windowedX: (appContainer.width + root.leftMargin)/2
1478+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
1458 name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
1482 name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
1459 extend: "normal"
1483 extend: "normal"
1485+ target: appDelegate
1460− PropertyChanges { target: appDelegate; windowedX: root.leftMargin; windowedY: windowedY;
1486+ windowedX: root.availableDesktopArea.x; windowedY: windowedY
1461− windowedWidth: appContainer.width - root.leftMargin; windowedHeight: windowedHeight }
1487+ windowedWidth: root.availableDesktopArea.width; windowedHeight: windowedHeight
1464 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
1491 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
1465 extend: "normal"
1492 extend: "normal"
1494+ target: appDelegate
1466− PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: PanelState.panelHeight;
1495+ windowedX: windowedX; windowedY: root.availableDesktopArea.y
1467− windowedWidth: windowedWidth; windowedHeight: appContainer.height - PanelState.panelHeight }
1496+ windowedWidth: windowedWidth; windowedHeight: root.availableDesktopArea.height
1470 name: "minimized"; when: appDelegate.minimized
1500 name: "minimized"; when: appDelegate.minimized
@@ -1592,7 +1622,7 @@ FocusScope {
1592 anchors.margins: touchControls.overlayShown ? borderThickness/2 : -borderThickness
1622 anchors.margins: touchControls.overlayShown ? borderThickness/2 : -borderThickness
1594 target: appDelegate
1624 target: appDelegate
1595− boundsItem: boundariesForWindowPlacement
1625+ boundsItem: root.availableDesktopArea
1596 minWidth: units.gu(10)
1626 minWidth: units.gu(10)
1597 minHeight: units.gu(10)
1627 minHeight: units.gu(10)
1598 borderThickness: units.gu(2)
1628 borderThickness: units.gu(2)
@@ -1615,13 +1645,14 @@ FocusScope {
1615 focus: true
1645 focus: true
1616 interactive: root.interactive
1646 interactive: root.interactive
1617 showDecoration: 1
1647 showDecoration: 1
1648+ decorationHeight: priv.windowDecorationHeight
1618 maximizeButtonShown: appDelegate.canBeMaximized
1649 maximizeButtonShown: appDelegate.canBeMaximized
1619 overlayShown: touchControls.overlayShown
1650 overlayShown: touchControls.overlayShown
1620 width: implicitWidth
1651 width: implicitWidth
1621 height: implicitHeight
1652 height: implicitHeight
1622 highlightSize: windowInfoItem.iconMargin / 2
1653 highlightSize: windowInfoItem.iconMargin / 2
1623− boundsItem: boundariesForWindowPlacement
1624 altDragEnabled: root.mode == "windowed"
1654 altDragEnabled: root.mode == "windowed"
1655+ boundsItem: root.availableDesktopArea
1626 requestedWidth: appDelegate.requestedWidth
1657 requestedWidth: appDelegate.requestedWidth
1627 requestedHeight: appDelegate.requestedHeight
1658 requestedHeight: appDelegate.requestedHeight
@@ -1684,7 +1715,7 @@ FocusScope {
1684 resizeArea: resizeArea
1715 resizeArea: resizeArea
1685 enabled: false
1716 enabled: false
1686 visible: enabled
1717 visible: enabled
1687− boundsItem: boundariesForWindowPlacement
1718+ boundsItem: root.availableDesktopArea
1689 onFakeMaximizeAnimationRequested: if (!appDelegate.maximized) fakeRectangle.maximize(amount, true)
1720 onFakeMaximizeAnimationRequested: if (!appDelegate.maximized) fakeRectangle.maximize(amount, true)
1690 onFakeMaximizeLeftAnimationRequested: if (!appDelegate.maximizedLeft) fakeRectangle.maximizeLeft(amount, true)
1721 onFakeMaximizeLeftAnimationRequested: if (!appDelegate.maximizedLeft) fakeRectangle.maximizeLeft(amount, true)
@@ -1805,9 +1836,18 @@ FocusScope {
1805 displacementX: appDelegate.clientAreaItem.x
1836 displacementX: appDelegate.clientAreaItem.x
1806 displacementY: appDelegate.clientAreaItem.y
1837 displacementY: appDelegate.clientAreaItem.y
1808− boundsItem: boundariesForWindowPlacement
1839+ boundsItem: root.availableDesktopArea
1840+ decorationHeight: priv.windowDecorationHeight
1810 z: childWindowRepeater.count - model.index
1842 z: childWindowRepeater.count - model.index
1846+ // some child surface in this tree got focus.
1847+ // Ensure we also have it at the top-level hierarchy
1848+ appDelegate.claimFocus();
@@ -1818,7 +1858,7 @@ FocusScope {
1818 FakeMaximizeDelegate {
1858 FakeMaximizeDelegate {
1819 id: fakeRectangle
1859 id: fakeRectangle
1820 target: priv.focusedAppDelegate
1860 target: priv.focusedAppDelegate
1821− leftMargin: root.leftMargin
1861+ leftMargin: root.availableDesktopArea.x
1822 appContainerWidth: appContainer.width
1862 appContainerWidth: appContainer.width
1823 appContainerHeight: appContainer.height
1863 appContainerHeight: appContainer.height