@@ -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
@@ -224,10 +231,30 @@ FocusScope {
224231 active: priv.focusedAppDelegate !== null
225232 }
226233
234+ GlobalShortcut {
235+ shortcut: Qt.ControlModifier|Qt.AltModifier|Qt.Key_T
236+ onTriggered: {
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]))
241+ break;
242+ }
243+ }
244+ }
245+
227246 QtObject {
228247 id: priv
229248 objectName: "DesktopStagePrivate"
230249
250+ function startApp(appId) {
251+ if (root.applicationManager.findApplication(appId)) {
252+ return root.applicationManager.requestFocusApplication(appId);
253+ } else {
254+ return root.applicationManager.startApplication(appId) !== null;
255+ }
256+ }
257+
231258 property var focusedAppDelegate: null
232259 property var foregroundMaximizedAppDelegate: null // for stuff like drop shadow and focusing maximized app by clicking panel
233260
@@ -347,6 +374,8 @@ FocusScope {
347374 }
348375
349376 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
377+
378+ readonly property real windowDecorationHeight: units.gu(3)
350379 }
351380
352381 Component.onCompleted: priv.updateMainAndSideStageIndexes();
@@ -567,7 +596,7 @@ FocusScope {
567596 id: spreadItem
568597 objectName: "spreadItem"
569598 anchors.fill: appContainer
570− leftMargin: root.leftMargin
599+ leftMargin: root.availableDesktopArea.x
571600 model: root.topLevelSurfaceList
572601 spreadFlickable: floatingFlickable
573602 z: 10
@@ -675,13 +704,6 @@ FocusScope {
675704 }
676705 }
677706
678− Item {
679− id: boundariesForWindowPlacement
680− anchors.fill: parent
681− anchors.topMargin: PanelState.panelHeight
682− visible: false
683− }
684−
685707 Repeater {
686708 id: appRepeater
687709 model: topLevelSurfaceList
@@ -779,7 +801,7 @@ FocusScope {
779801 target: appDelegate
780802 property: "y"
781803 value: appDelegate.requestedY -
782− Math.min(appDelegate.requestedY - PanelState.panelHeight,
804+ Math.min(appDelegate.requestedY - root.availableDesktopArea.y,
783805 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
784806 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
785807 && root.inputMethodRect.height > 0
@@ -797,8 +819,8 @@ FocusScope {
797819 angleDiff = (360 + angleDiff) % 360;
798820 if (angleDiff === 90 || angleDiff === 270) {
799821 var aux = decoratedWindow.requestedHeight;
800− decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.decorationHeight;
801− decoratedWindow.requestedWidth = aux - decoratedWindow.decorationHeight;
822+ decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.actualDecorationHeight;
823+ decoratedWindow.requestedWidth = aux - decoratedWindow.actualDecorationHeight;
802824 }
803825 }
804826 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
@@ -899,12 +921,13 @@ FocusScope {
899921 priv.updateMainAndSideStageIndexes();
900922 }
901923 appDelegate.focus = true;
924+ priv.focusedAppDelegate = appDelegate;
902925 }
903926
904927 function updateQmlFocusFromMirSurfaceFocus() {
905928 if (model.window.focused) {
906929 claimFocus();
907− priv.focusedAppDelegate = appDelegate;
930+ decoratedWindow.focus = true;
908931 }
909932 }
910933
@@ -913,8 +936,8 @@ FocusScope {
913936 target: appDelegate
914937 screenWidth: appContainer.width
915938 screenHeight: appContainer.height
916− leftMargin: root.leftMargin
917− minimumY: boundariesForWindowPlacement.y
939+ leftMargin: root.availableDesktopArea.x
940+ minimumY: root.availableDesktopArea.y
918941 }
919942
920943 Connections {
@@ -1166,7 +1189,7 @@ FocusScope {
11661189
11671190 StagedRightEdgeMaths {
11681191 id: stagedRightEdgeMaths
1169− sceneWidth: appContainer.width - root.leftMargin
1192+ sceneWidth: root.availableDesktopArea.width
11701193 sceneHeight: appContainer.height
11711194 isMainStageApp: priv.mainStageDelegate == appDelegate
11721195 isSideStageApp: priv.sideStageDelegate == appDelegate
@@ -1177,7 +1200,7 @@ FocusScope {
11771200 progress: 0
11781201 targetHeight: spreadItem.stackHeight
11791202 targetX: spreadMaths.targetX
1180− startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1203+ startY: appDelegate.fullscreen ? 0 : root.availableDesktopArea.y
11811204 targetY: spreadMaths.targetY
11821205 targetAngle: spreadMaths.targetAngle
11831206 targetScale: spreadMaths.targetScale
@@ -1298,9 +1321,9 @@ FocusScope {
12981321 PropertyChanges {
12991322 target: appDelegate
13001323 x: stageMaths.itemX
1301− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1324+ y: root.availableDesktopArea.y
13021325 requestedWidth: appContainer.width
1303− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1326+ requestedHeight: root.availableDesktopArea.height
13041327 visuallyMaximized: true
13051328 visible: appDelegate.x < root.width
13061329 }
@@ -1330,10 +1353,10 @@ FocusScope {
13301353 PropertyChanges {
13311354 target: appDelegate
13321355 x: stageMaths.itemX
1333− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1356+ y: root.availableDesktopArea.y
13341357 z: stageMaths.itemZ
13351358 requestedWidth: stageMaths.itemWidth
1336− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1359+ requestedHeight: root.availableDesktopArea.height
13371360 visuallyMaximized: true
13381361 visible: appDelegate.x < root.width
13391362 }
@@ -1354,11 +1377,11 @@ FocusScope {
13541377 name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
13551378 PropertyChanges {
13561379 target: appDelegate;
1357− requestedX: root.leftMargin;
1380+ requestedX: root.availableDesktopArea.x;
13581381 requestedY: 0;
13591382 visuallyMinimized: false;
13601383 visuallyMaximized: true
1361− requestedWidth: appContainer.width - root.leftMargin;
1384+ requestedWidth: root.availableDesktopArea.width;
13621385 requestedHeight: appContainer.height;
13631386 }
13641387 PropertyChanges { target: touchControls; enabled: true }
@@ -1391,6 +1414,7 @@ FocusScope {
13911414 when: appDelegate.windowState == WindowStateStorage.WindowStateRestored
13921415 extend: "normal"
13931416 PropertyChanges {
1417+ restoreEntryValues: false
13941418 target: appDelegate;
13951419 windowedX: restoredX;
13961420 windowedY: restoredY;
@@ -1401,10 +1425,10 @@ FocusScope {
14011425 extend: "normal"
14021426 PropertyChanges {
14031427 target: appDelegate
1404− windowedX: root.leftMargin
1405− windowedY: PanelState.panelHeight
1406− windowedWidth: (appContainer.width - root.leftMargin)/2
1407− 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
14081432 }
14091433 },
14101434 State {
@@ -1412,7 +1436,7 @@ FocusScope {
14121436 extend: "maximizedLeft"
14131437 PropertyChanges {
14141438 target: appDelegate;
1415− windowedX: (appContainer.width + root.leftMargin)/2
1439+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14161440 }
14171441 },
14181442 State {
@@ -1420,10 +1444,10 @@ FocusScope {
14201444 extend: "normal"
14211445 PropertyChanges {
14221446 target: appDelegate
1423− windowedX: root.leftMargin
1424− windowedY: PanelState.panelHeight
1425− windowedWidth: (appContainer.width - root.leftMargin)/2
1426− 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
14271451 }
14281452 },
14291453 State {
@@ -1431,7 +1455,7 @@ FocusScope {
14311455 extend: "maximizedTopLeft"
14321456 PropertyChanges {
14331457 target: appDelegate
1434− windowedX: (appContainer.width + root.leftMargin)/2
1458+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14351459 }
14361460 },
14371461 State {
@@ -1439,10 +1463,10 @@ FocusScope {
14391463 extend: "normal"
14401464 PropertyChanges {
14411465 target: appDelegate
1442− windowedX: root.leftMargin
1443− windowedY: (appContainer.height + PanelState.panelHeight)/2
1444− windowedWidth: (appContainer.width - root.leftMargin)/2
1445− 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
14461470 }
14471471 },
14481472 State {
@@ -1450,20 +1474,26 @@ FocusScope {
14501474 extend: "maximizedBottomLeft"
14511475 PropertyChanges {
14521476 target: appDelegate
1453− windowedX: (appContainer.width + root.leftMargin)/2
1477+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14541478 }
14551479 },
14561480 State {
14571481 name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
14581482 extend: "normal"
1459− PropertyChanges { target: appDelegate; windowedX: root.leftMargin; windowedY: windowedY;
1460− 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+ }
14611488 },
14621489 State {
14631490 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
14641491 extend: "normal"
1465− PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: PanelState.panelHeight;
1466− 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+ }
14671497 },
14681498 State {
14691499 name: "minimized"; when: appDelegate.minimized
@@ -1591,7 +1621,7 @@ FocusScope {
15911621 anchors.margins: touchControls.overlayShown ? borderThickness/2 : -borderThickness
15921622
15931623 target: appDelegate
1594− boundsItem: boundariesForWindowPlacement
1624+ boundsItem: root.availableDesktopArea
15951625 minWidth: units.gu(10)
15961626 minHeight: units.gu(10)
15971627 borderThickness: units.gu(2)
@@ -1614,13 +1644,14 @@ FocusScope {
16141644 focus: true
16151645 interactive: root.interactive
16161646 showDecoration: 1
1647+ decorationHeight: priv.windowDecorationHeight
16171648 maximizeButtonShown: appDelegate.canBeMaximized
16181649 overlayShown: touchControls.overlayShown
16191650 width: implicitWidth
16201651 height: implicitHeight
16211652 highlightSize: windowInfoItem.iconMargin / 2
1622− boundsItem: boundariesForWindowPlacement
16231653 altDragEnabled: root.mode == "windowed"
1654+ boundsItem: root.availableDesktopArea
16241655
16251656 requestedWidth: appDelegate.requestedWidth
16261657 requestedHeight: appDelegate.requestedHeight
@@ -1683,7 +1714,7 @@ FocusScope {
16831714 resizeArea: resizeArea
16841715 enabled: false
16851716 visible: enabled
1686− boundsItem: boundariesForWindowPlacement
1717+ boundsItem: root.availableDesktopArea
16871718
16881719 onFakeMaximizeAnimationRequested: if (!appDelegate.maximized) fakeRectangle.maximize(amount, true)
16891720 onFakeMaximizeLeftAnimationRequested: if (!appDelegate.maximizedLeft) fakeRectangle.maximizeLeft(amount, true)
@@ -1804,9 +1835,18 @@ FocusScope {
18041835 displacementX: appDelegate.clientAreaItem.x
18051836 displacementY: appDelegate.clientAreaItem.y
18061837
1807− boundsItem: boundariesForWindowPlacement
1838+ boundsItem: root.availableDesktopArea
1839+ decorationHeight: priv.windowDecorationHeight
18081840
18091841 z: childWindowRepeater.count - model.index
1842+
1843+ onFocusChanged: {
1844+ if (focus) {
1845+ // some child surface in this tree got focus.
1846+ // Ensure we also have it at the top-level hierarchy
1847+ appDelegate.claimFocus();
1848+ }
1849+ }
18101850 }
18111851 }
18121852 }
@@ -1817,7 +1857,7 @@ FocusScope {
18171857 FakeMaximizeDelegate {
18181858 id: fakeRectangle
18191859 target: priv.focusedAppDelegate
1820− leftMargin: root.leftMargin
1860+ leftMargin: root.availableDesktopArea.x
18211861 appContainerWidth: appContainer.width
18221862 appContainerHeight: appContainer.height
18231863 }