@@ -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,8 +374,8 @@ FocusScope {
347374 }
348375
349376 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
350−
351377 property bool anyWindowAnimating: false
378+ readonly property real windowDecorationHeight: units.gu(3)
352379 }
353380
354381 Component.onCompleted: priv.updateMainAndSideStageIndexes();
@@ -569,7 +596,7 @@ FocusScope {
569596 id: spreadItem
570597 objectName: "spreadItem"
571598 anchors.fill: appContainer
572− leftMargin: root.leftMargin
599+ leftMargin: root.availableDesktopArea.x
573600 model: root.topLevelSurfaceList
574601 spreadFlickable: floatingFlickable
575602 z: 10
@@ -677,13 +704,6 @@ FocusScope {
677704 }
678705 }
679706
680− Item {
681− id: boundariesForWindowPlacement
682− anchors.fill: parent
683− anchors.topMargin: PanelState.panelHeight
684− visible: false
685− }
686−
687707 Repeater {
688708 id: appRepeater
689709 model: topLevelSurfaceList
@@ -781,7 +801,7 @@ FocusScope {
781801 target: appDelegate
782802 property: "y"
783803 value: appDelegate.requestedY -
784− Math.min(appDelegate.requestedY - PanelState.panelHeight,
804+ Math.min(appDelegate.requestedY - root.availableDesktopArea.y,
785805 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
786806 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
787807 && root.inputMethodRect.height > 0
@@ -799,8 +819,8 @@ FocusScope {
799819 angleDiff = (360 + angleDiff) % 360;
800820 if (angleDiff === 90 || angleDiff === 270) {
801821 var aux = decoratedWindow.requestedHeight;
802− decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.decorationHeight;
803− decoratedWindow.requestedWidth = aux - decoratedWindow.decorationHeight;
822+ decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.actualDecorationHeight;
823+ decoratedWindow.requestedWidth = aux - decoratedWindow.actualDecorationHeight;
804824 }
805825 }
806826 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
@@ -901,12 +921,13 @@ FocusScope {
901921 priv.updateMainAndSideStageIndexes();
902922 }
903923 appDelegate.focus = true;
924+ priv.focusedAppDelegate = appDelegate;
904925 }
905926
906927 function updateQmlFocusFromMirSurfaceFocus() {
907928 if (model.window.focused) {
908929 claimFocus();
909− priv.focusedAppDelegate = appDelegate;
930+ decoratedWindow.focus = true;
910931 }
911932 }
912933
@@ -915,8 +936,8 @@ FocusScope {
915936 target: appDelegate
916937 screenWidth: appContainer.width
917938 screenHeight: appContainer.height
918− leftMargin: root.leftMargin
919− minimumY: boundariesForWindowPlacement.y
939+ leftMargin: root.availableDesktopArea.x
940+ minimumY: root.availableDesktopArea.y
920941 }
921942
922943 Connections {
@@ -1169,7 +1190,7 @@ FocusScope {
11691190
11701191 StagedRightEdgeMaths {
11711192 id: stagedRightEdgeMaths
1172− sceneWidth: appContainer.width - root.leftMargin
1193+ sceneWidth: root.availableDesktopArea.width
11731194 sceneHeight: appContainer.height
11741195 isMainStageApp: priv.mainStageDelegate == appDelegate
11751196 isSideStageApp: priv.sideStageDelegate == appDelegate
@@ -1180,7 +1201,7 @@ FocusScope {
11801201 progress: 0
11811202 targetHeight: spreadItem.stackHeight
11821203 targetX: spreadMaths.targetX
1183− startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1204+ startY: appDelegate.fullscreen ? 0 : root.availableDesktopArea.y
11841205 targetY: spreadMaths.targetY
11851206 targetAngle: spreadMaths.targetAngle
11861207 targetScale: spreadMaths.targetScale
@@ -1301,9 +1322,9 @@ FocusScope {
13011322 PropertyChanges {
13021323 target: appDelegate
13031324 x: stageMaths.itemX
1304− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1325+ y: root.availableDesktopArea.y
13051326 requestedWidth: appContainer.width
1306− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1327+ requestedHeight: root.availableDesktopArea.height
13071328 visuallyMaximized: true
13081329 visible: appDelegate.x < root.width
13091330 }
@@ -1333,10 +1354,10 @@ FocusScope {
13331354 PropertyChanges {
13341355 target: appDelegate
13351356 x: stageMaths.itemX
1336− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1357+ y: root.availableDesktopArea.y
13371358 z: stageMaths.itemZ
13381359 requestedWidth: stageMaths.itemWidth
1339− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1360+ requestedHeight: root.availableDesktopArea.height
13401361 visuallyMaximized: true
13411362 visible: appDelegate.x < root.width
13421363 }
@@ -1357,11 +1378,11 @@ FocusScope {
13571378 name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
13581379 PropertyChanges {
13591380 target: appDelegate;
1360− requestedX: root.leftMargin;
1381+ requestedX: root.availableDesktopArea.x;
13611382 requestedY: 0;
13621383 visuallyMinimized: false;
13631384 visuallyMaximized: true
1364− requestedWidth: appContainer.width - root.leftMargin;
1385+ requestedWidth: root.availableDesktopArea.width;
13651386 requestedHeight: appContainer.height;
13661387 }
13671388 PropertyChanges { target: touchControls; enabled: true }
@@ -1394,6 +1415,7 @@ FocusScope {
13941415 when: appDelegate.windowState == WindowStateStorage.WindowStateRestored
13951416 extend: "normal"
13961417 PropertyChanges {
1418+ restoreEntryValues: false
13971419 target: appDelegate;
13981420 windowedX: restoredX;
13991421 windowedY: restoredY;
@@ -1404,10 +1426,10 @@ FocusScope {
14041426 extend: "normal"
14051427 PropertyChanges {
14061428 target: appDelegate
1407− windowedX: root.leftMargin
1408− windowedY: PanelState.panelHeight
1409− windowedWidth: (appContainer.width - root.leftMargin)/2
1410− windowedHeight: appContainer.height - PanelState.panelHeight
1429+ windowedX: root.availableDesktopArea.x
1430+ windowedY: root.availableDesktopArea.y
1431+ windowedWidth: root.availableDesktopArea.width / 2
1432+ windowedHeight: root.availableDesktopArea.height
14111433 }
14121434 },
14131435 State {
@@ -1415,7 +1437,7 @@ FocusScope {
14151437 extend: "maximizedLeft"
14161438 PropertyChanges {
14171439 target: appDelegate;
1418− windowedX: (appContainer.width + root.leftMargin)/2
1440+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14191441 }
14201442 },
14211443 State {
@@ -1423,10 +1445,10 @@ FocusScope {
14231445 extend: "normal"
14241446 PropertyChanges {
14251447 target: appDelegate
1426− windowedX: root.leftMargin
1427− windowedY: PanelState.panelHeight
1428− windowedWidth: (appContainer.width - root.leftMargin)/2
1429− windowedHeight: (appContainer.height - PanelState.panelHeight)/2
1448+ windowedX: root.availableDesktopArea.x
1449+ windowedY: root.availableDesktopArea.y
1450+ windowedWidth: root.availableDesktopArea.width / 2
1451+ windowedHeight: root.availableDesktopArea.height / 2
14301452 }
14311453 },
14321454 State {
@@ -1434,7 +1456,7 @@ FocusScope {
14341456 extend: "maximizedTopLeft"
14351457 PropertyChanges {
14361458 target: appDelegate
1437− windowedX: (appContainer.width + root.leftMargin)/2
1459+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14381460 }
14391461 },
14401462 State {
@@ -1442,10 +1464,10 @@ FocusScope {
14421464 extend: "normal"
14431465 PropertyChanges {
14441466 target: appDelegate
1445− windowedX: root.leftMargin
1446− windowedY: (appContainer.height + PanelState.panelHeight)/2
1447− windowedWidth: (appContainer.width - root.leftMargin)/2
1448− windowedHeight: appContainer.height/2
1467+ windowedX: root.availableDesktopArea.x
1468+ windowedY: root.availableDesktopArea.y + (root.availableDesktopArea.height / 2)
1469+ windowedWidth: root.availableDesktopArea.width / 2
1470+ windowedHeight: root.availableDesktopArea.height / 2
14491471 }
14501472 },
14511473 State {
@@ -1453,20 +1475,26 @@ FocusScope {
14531475 extend: "maximizedBottomLeft"
14541476 PropertyChanges {
14551477 target: appDelegate
1456− windowedX: (appContainer.width + root.leftMargin)/2
1478+ windowedX: root.availableDesktopArea.x + (root.availableDesktopArea.width / 2)
14571479 }
14581480 },
14591481 State {
14601482 name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
14611483 extend: "normal"
1462− PropertyChanges { target: appDelegate; windowedX: root.leftMargin; windowedY: windowedY;
1463− windowedWidth: appContainer.width - root.leftMargin; windowedHeight: windowedHeight }
1484+ PropertyChanges {
1485+ target: appDelegate
1486+ windowedX: root.availableDesktopArea.x; windowedY: windowedY
1487+ windowedWidth: root.availableDesktopArea.width; windowedHeight: windowedHeight
1488+ }
14641489 },
14651490 State {
14661491 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
14671492 extend: "normal"
1468− PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: PanelState.panelHeight;
1469− windowedWidth: windowedWidth; windowedHeight: appContainer.height - PanelState.panelHeight }
1493+ PropertyChanges {
1494+ target: appDelegate
1495+ windowedX: windowedX; windowedY: root.availableDesktopArea.y
1496+ windowedWidth: windowedWidth; windowedHeight: root.availableDesktopArea.height
1497+ }
14701498 },
14711499 State {
14721500 name: "minimized"; when: appDelegate.minimized
@@ -1595,7 +1623,7 @@ FocusScope {
15951623 anchors.margins: touchControls.overlayShown ? borderThickness/2 : -borderThickness
15961624
15971625 target: appDelegate
1598− boundsItem: boundariesForWindowPlacement
1626+ boundsItem: root.availableDesktopArea
15991627 minWidth: units.gu(10)
16001628 minHeight: units.gu(10)
16011629 borderThickness: units.gu(2)
@@ -1618,13 +1646,14 @@ FocusScope {
16181646 focus: true
16191647 interactive: root.interactive
16201648 showDecoration: 1
1649+ decorationHeight: priv.windowDecorationHeight
16211650 maximizeButtonShown: appDelegate.canBeMaximized
16221651 overlayShown: touchControls.overlayShown
16231652 width: implicitWidth
16241653 height: implicitHeight
16251654 highlightSize: windowInfoItem.iconMargin / 2
1626− boundsItem: boundariesForWindowPlacement
16271655 altDragEnabled: root.mode == "windowed"
1656+ boundsItem: root.availableDesktopArea
16281657
16291658 requestedWidth: appDelegate.requestedWidth
16301659 requestedHeight: appDelegate.requestedHeight
@@ -1687,7 +1716,7 @@ FocusScope {
16871716 resizeArea: resizeArea
16881717 enabled: false
16891718 visible: enabled
1690− boundsItem: boundariesForWindowPlacement
1719+ boundsItem: root.availableDesktopArea
16911720
16921721 onFakeMaximizeAnimationRequested: if (!appDelegate.maximized) fakeRectangle.maximize(amount, true)
16931722 onFakeMaximizeLeftAnimationRequested: if (!appDelegate.maximizedLeft) fakeRectangle.maximizeLeft(amount, true)
@@ -1808,9 +1837,18 @@ FocusScope {
18081837 displacementX: appDelegate.clientAreaItem.x
18091838 displacementY: appDelegate.clientAreaItem.y
18101839
1811− boundsItem: boundariesForWindowPlacement
1840+ boundsItem: root.availableDesktopArea
1841+ decorationHeight: priv.windowDecorationHeight
18121842
18131843 z: childWindowRepeater.count - model.index
1844+
1845+ onFocusChanged: {
1846+ if (focus) {
1847+ // some child surface in this tree got focus.
1848+ // Ensure we also have it at the top-level hierarchy
1849+ appDelegate.claimFocus();
1850+ }
1851+ }
18141852 }
18151853 }
18161854 }
@@ -1821,7 +1859,7 @@ FocusScope {
18211859 FakeMaximizeDelegate {
18221860 id: fakeRectangle
18231861 target: priv.focusedAppDelegate
1824− leftMargin: root.leftMargin
1862+ leftMargin: root.availableDesktopArea.x
18251863 appContainerWidth: appContainer.width
18261864 appContainerHeight: appContainer.height
18271865 }