on xenial help sign in
Provide window/surface close shortcuts across all the stages (LP: #1578392, #1606528)
5052176Lukáš Tinkl
qml/Stages/AbstractStage.qml+9
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18import Ubuntu.Components 1.3
18import Ubuntu.Components 1.3
19+import GlobalShortcut 1.0
19import GSettings 1.0
20import GSettings 1.0
20
21
21FocusScope {
22FocusScope {
@@ -78,4 +79,12 @@ FocusScope {
78 color: "#060606"
79 color: "#060606"
79 anchors.fill: parent
80 anchors.fill: parent
80 }
81 }
82+
83+ // shared Alt+F4 functionality
84+ function closeFocusedDelegate() {} // to be implemented by stages
85+
86+ GlobalShortcut {
87+ shortcut: Qt.AltModifier|Qt.Key_F4
88+ onTriggered: closeFocusedDelegate()
89+ }
81}
90}
qml/Stages/DesktopStage.qml+8−8
@@ -36,6 +36,11 @@ AbstractStage {
36 edgeBarrier.push(amount);
36 edgeBarrier.push(amount);
37 }
37 }
38 }
38 }
39+ function closeFocusedDelegate() {
40+ if (priv.focusedAppDelegate && !priv.focusedAppDelegate.isDash) {
41+ priv.focusedAppDelegate.close();
42+ }
43+ }
39
44
40 // Used by TutorialRight
45 // Used by TutorialRight
41 property bool spreadShown: spread.state == "altTab"
46 property bool spreadShown: spread.state == "altTab"
@@ -47,13 +52,6 @@ AbstractStage {
47
52
48 orientationChangesEnabled: true
53 orientationChangesEnabled: true
49
54
50− GlobalShortcut {
51− id: closeWindowShortcut
52− shortcut: Qt.AltModifier|Qt.Key_F4
53− onTriggered: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }
54− active: priv.focusedAppDelegate !== null
55− }
56−
57 GlobalShortcut {
55 GlobalShortcut {
58 id: showSpreadShortcut
56 id: showSpreadShortcut
59 shortcut: Qt.MetaModifier|Qt.Key_W
57 shortcut: Qt.MetaModifier|Qt.Key_W
@@ -205,7 +203,7 @@ AbstractStage {
205 Binding {
203 Binding {
206 target: PanelState
204 target: PanelState
207 property: "closeButtonShown"
205 property: "closeButtonShown"
208− value: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized && priv.focusedAppDelegate.application.appId !== "unity8-dash"
206+ value: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized && !priv.focusedAppDelegate.isDash
209 }
207 }
210
208
211 Component.onDestruction: {
209 Component.onDestruction: {
@@ -337,6 +335,8 @@ AbstractStage {
337 readonly property var surface: model.surface
335 readonly property var surface: model.surface
338 readonly property alias resizeArea: resizeArea
336 readonly property alias resizeArea: resizeArea
339
337
338+ readonly property bool isDash: model.application.appId == "unity8-dash"
339+
340 function claimFocus() {
340 function claimFocus() {
341 if (spread.state == "altTab") {
341 if (spread.state == "altTab") {
342 spread.cancel();
342 spread.cancel();
qml/Stages/PhoneStage.qml+8−2
@@ -108,6 +108,12 @@ AbstractStage {
108 }
108 }
109 }
109 }
110
110
111+ function closeFocusedDelegate() {
112+ if (priv.focusedAppDelegate && priv.focusedAppDelegate.closeable) {
113+ priv.focusedAppDelegate.closed();
114+ }
115+ }
116+
111 mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null
117 mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null
112
118
113 orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled
119 orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled
@@ -465,13 +471,13 @@ AbstractStage {
465 model: topLevelSurfaceList
471 model: topLevelSurfaceList
466
472
467 onItemRemoved: {
473 onItemRemoved: {
468− // Unless we're closing the app ourselves in the spread,
474+ // Unless we're closing the app ourselves,
469 // lets make sure the spread doesn't mess up by the changing app list.
475 // lets make sure the spread doesn't mess up by the changing app list.
470 if (spreadView.closingIndex == -1) {
476 if (spreadView.closingIndex == -1) {
471 spreadView.phase = 0;
477 spreadView.phase = 0;
472 spreadView.contentX = -spreadView.shift;
478 spreadView.contentX = -spreadView.shift;
473− focusTopMostApp();
474 }
479 }
480+ focusTopMostApp();
475 }
481 }
476 function focusTopMostApp() {
482 function focusTopMostApp() {
477 if (spreadRepeater.count > 0) {
483 if (spreadRepeater.count > 0) {
qml/Stages/TabletStage.qml+8−2
@@ -84,6 +84,12 @@ AbstractStage {
84 }
84 }
85 }
85 }
86
86
87+ function closeFocusedDelegate() {
88+ if (priv.focusedAppDelegate && priv.focusedAppDelegate.closeable) {
89+ priv.focusedAppDelegate.closed();
90+ }
91+ }
92+
87 orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
93 orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
88
94
89 mainApp: {
95 mainApp: {
@@ -707,13 +713,13 @@ AbstractStage {
707
713
708 onItemRemoved: {
714 onItemRemoved: {
709 priv.updateMainAndSideStageIndexes();
715 priv.updateMainAndSideStageIndexes();
710− // Unless we're closing the app ourselves in the spread,
716+ // Unless we're closing the app ourselves,
711 // lets make sure the spread doesn't mess up by the changing app list.
717 // lets make sure the spread doesn't mess up by the changing app list.
712 if (spreadView.closingIndex == -1) {
718 if (spreadView.closingIndex == -1) {
713 spreadView.phase = 0;
719 spreadView.phase = 0;
714 spreadView.contentX = -spreadView.shift;
720 spreadView.contentX = -spreadView.shift;
715− focusTopMostApp();
716 }
721 }
722+ focusTopMostApp();
717 }
723 }
718 function focusTopMostApp() {
724 function focusTopMostApp() {
719 if (spreadRepeater.count > 0) {
725 if (spreadRepeater.count > 0) {
tests/qmltests/tst_Shell.qml+30
@@ -2506,5 +2506,35 @@ Rectangle {
2506 verify(greeter.shown);
2506 verify(greeter.shown);
2507 verify(greeter.locked);
2507 verify(greeter.locked);
2508 }
2508 }
2509+
2510+ function test_closeFocusedDelegate_data() {
2511+ return [
2512+ { tag: "phone" },
2513+ { tag: "tablet" },
2514+ { tag: "desktop" }
2515+ ]
2516+ }
2517+
2518+ function test_closeFocusedDelegate(data) {
2519+ loadShell(data.tag);
2520+ shell.usageScenario = data.tag;
2521+ waitForRendering(shell);
2522+ swipeAwayGreeter();
2523+
2524+ var app2SurfaceId = topLevelSurfaceList.nextId;
2525+ var app2 = ApplicationManager.startApplication("calendar-app");
2526+ waitUntilAppWindowIsFullyLoaded(app2SurfaceId);
2527+
2528+ var app1SurfaceId = topLevelSurfaceList.nextId;
2529+ var app1 = ApplicationManager.startApplication("dialer-app")
2530+ waitUntilAppWindowIsFullyLoaded(app1SurfaceId);
2531+
2532+ var countBeforeClose = topLevelSurfaceList.count;
2533+
2534+ keyClick(Qt.Key_F4, Qt.AltModifier);
2535+
2536+ tryCompare(topLevelSurfaceList, "count", countBeforeClose - 1);
2537+ tryCompareFunction(function() { return ApplicationManager.focusedApplicationId; }, "calendar-app");
2538+ }
2509 }
2539 }
2510}
2540}