on xenial help sign in
Fixes for activating minimized windows and restoring fullscreen ones (LP: #1656808, #1658937, #1658938)
8146597Lukáš Tinkl
qml/Shell.qml+2−1
@@ -523,12 +523,13 @@ StyledItem {
523 hides: [launcher]
523 hides: [launcher]
524 available: (!greeter || !greeter.shown)
524 available: (!greeter || !greeter.shown)
525 && !shell.waitingOnGreeter
525 && !shell.waitingOnGreeter
526+ && !stage.spreadShown
526 }
527 }
527
528
528 readonly property bool focusedSurfaceIsFullscreen: topLevelSurfaceList.focusedWindow
529 readonly property bool focusedSurfaceIsFullscreen: topLevelSurfaceList.focusedWindow
529 ? topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState
530 ? topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState
530 : false
531 : false
531− fullscreenMode: (focusedSurfaceIsFullscreen && !LightDMService.greeter.active && launcher.progress == 0)
532+ fullscreenMode: (focusedSurfaceIsFullscreen && !LightDMService.greeter.active && launcher.progress == 0 && !stage.spreadShown)
532 || greeter.hasLockedApp
533 || greeter.hasLockedApp
533 greeterShown: greeter && greeter.shown
534 greeterShown: greeter && greeter.shown
534 }
535 }
qml/Stage/Stage.qml+15−5
@@ -101,6 +101,8 @@ FocusScope {
101 // No we didn't, do a quick alt-tab
101 // No we didn't, do a quick alt-tab
102 if (appRepeater.count > 1) {
102 if (appRepeater.count > 1) {
103 appRepeater.itemAt(1).activate();
103 appRepeater.itemAt(1).activate();
104+ } else if (appRepeater.count > 0) {
105+ appRepeater.itemAt(0).activate(); // quick alt-tab to the only (minimized) window should still activate it
104 }
106 }
105 }
107 }
106 }
108 }
@@ -811,7 +813,7 @@ FocusScope {
811 maximizedTopLeft || maximizedTopRight || maximizedBottomLeft || maximizedBottomRight
813 maximizedTopLeft || maximizedTopRight || maximizedBottomLeft || maximizedBottomRight
812
814
813 readonly property bool minimized: windowState & WindowStateStorage.WindowStateMinimized
815 readonly property bool minimized: windowState & WindowStateStorage.WindowStateMinimized
814− readonly property bool fullscreen: window.state === Mir.FullscreenState
816+ readonly property bool fullscreen: windowState === WindowStateStorage.WindowStateFullscreen
815
817
816 readonly property bool canBeMaximized: canBeMaximizedHorizontally && canBeMaximizedVertically
818 readonly property bool canBeMaximized: canBeMaximizedHorizontally && canBeMaximizedVertically
817 readonly property bool canBeMaximizedLeftRight: (maximumWidth == 0 || maximumWidth >= appContainer.width/2) &&
819 readonly property bool canBeMaximizedLeftRight: (maximumWidth == 0 || maximumWidth >= appContainer.width/2) &&
@@ -822,7 +824,10 @@ FocusScope {
822 readonly property bool canBeMaximizedVertically: maximumHeight == 0 || maximumHeight >= appContainer.height
824 readonly property bool canBeMaximizedVertically: maximumHeight == 0 || maximumHeight >= appContainer.height
823 readonly property alias orientationChangesEnabled: decoratedWindow.orientationChangesEnabled
825 readonly property alias orientationChangesEnabled: decoratedWindow.orientationChangesEnabled
824
826
827+ // TODO drop our own windowType once Mir/Miral/Qtmir gets in sync with ours
825 property int windowState: WindowStateStorage.WindowStateNormal
828 property int windowState: WindowStateStorage.WindowStateNormal
829+ property int prevWindowState: WindowStateStorage.WindowStateRestored
830+
826 property bool animationsEnabled: true
831 property bool animationsEnabled: true
827 property alias title: decoratedWindow.title
832 property alias title: decoratedWindow.title
828 readonly property string appName: model.application ? model.application.name : ""
833 readonly property string appName: model.application ? model.application.name : ""
@@ -877,9 +882,6 @@ FocusScope {
877 }
882 }
878 priv.updateMainAndSideStageIndexes();
883 priv.updateMainAndSideStageIndexes();
879 }
884 }
880− if (root.mode == "windowed") {
881− appDelegate.restore(true /* animated */, appDelegate.windowState);
882− }
883 appDelegate.focus = true;
885 appDelegate.focus = true;
884 }
886 }
885
887
@@ -929,7 +931,14 @@ FocusScope {
929 } else if (model.window.state === Mir.MaximizedBottomRightState) {
931 } else if (model.window.state === Mir.MaximizedBottomRightState) {
930 appDelegate.maximizeBottomRight();
932 appDelegate.maximizeBottomRight();
931 } else if (model.window.state === Mir.RestoredState) {
933 } else if (model.window.state === Mir.RestoredState) {
934+ if (appDelegate.fullscreen && appDelegate.prevWindowState != WindowStateStorage.WindowStateRestored) {
935+ model.window.requestState(WindowStateStorage.toMirState(appDelegate.prevWindowState));
936+ } else {
932− appDelegate.restore();
937+ appDelegate.restore();
938+ }
939+ } else if (model.window.state === Mir.FullscreenState) {
940+ appDelegate.prevWindowState = appDelegate.windowState;
941+ appDelegate.windowState = WindowStateStorage.WindowStateFullscreen;
933 }
942 }
934 }
943 }
935 }
944 }
@@ -1031,6 +1040,7 @@ FocusScope {
1031 animationsEnabled = (animated === undefined) || animated;
1040 animationsEnabled = (animated === undefined) || animated;
1032 windowState = state || WindowStateStorage.WindowStateRestored;
1041 windowState = state || WindowStateStorage.WindowStateRestored;
1033 windowState &= ~WindowStateStorage.WindowStateMinimized; // clear the minimized bit
1042 windowState &= ~WindowStateStorage.WindowStateMinimized; // clear the minimized bit
1043+ prevWindowState = windowState;
1034 }
1044 }
1035
1045
1036 function playFocusAnimation() {
1046 function playFocusAnimation() {
tests/mocks/Unity/Application/SurfaceManager.cpp+4−5
@@ -211,8 +211,6 @@ void SurfaceManager::activate(unityapi::MirSurfaceInterface *apiSurface)
211
211
212void SurfaceManager::onStateRequested(MirSurface *surface, Mir::State state)
212void SurfaceManager::onStateRequested(MirSurface *surface, Mir::State state)
213{
213{
214− Q_ASSERT(!m_underModification);
215−
216 DEBUG_MSG("("<<surface<<","<<state<<") started");
214 DEBUG_MSG("("<<surface<<","<<state<<") started");
217 Q_EMIT modificationsStarted();
215 Q_EMIT modificationsStarted();
218 m_underModification = true;
216 m_underModification = true;
@@ -266,9 +264,10 @@ void SurfaceManager::focusFirstAvailableSurface()
266 if (m_focusedSurface) {
264 if (m_focusedSurface) {
267 m_focusedSurface->setFocused(false);
265 m_focusedSurface->setFocused(false);
268 }
266 }
269− if (chosenSurface) {
267+
270− chosenSurface->setFocused(true);
268+ chosenSurface->setFocused(true);
271− }
269+ doRaise(chosenSurface);
270+
272 m_focusedSurface = chosenSurface;
271 m_focusedSurface = chosenSurface;
273}
272}
274
273
tests/qmltests/tst_Shell.qml+59
@@ -335,6 +335,8 @@ Rectangle {
335 Row {
335 Row {
336 CheckBox {
336 CheckBox {
337 id: fullscreeAppCheck
337 id: fullscreeAppCheck
338+ activeFocusOnPress: false
339+ activeFocusOnTab: false
338
340
339 onTriggered: {
341 onTriggered: {
340 if (!topLevelSurfaceList.focusedWindow) return;
342 if (!topLevelSurfaceList.focusedWindow) return;
@@ -2779,5 +2781,62 @@ Rectangle {
2779 }
2781 }
2780 tryCompareFunction(function() { return drawer.visible; }, false);
2782 tryCompareFunction(function() { return drawer.visible; }, false);
2781 }
2783 }
2784+
2785+ function test_restoreFromFullscreen() {
2786+ loadShell("desktop");
2787+ shell.usageScenario = "desktop";
2788+ waitForRendering(shell);
2789+ swipeAwayGreeter();
2790+
2791+ var appSurfaceId = topLevelSurfaceList.nextId;
2792+ var app = ApplicationManager.startApplication("dialer-app")
2793+ waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2794+
2795+ // start dialer
2796+ var appContainer = findChild(shell, "appContainer");
2797+ var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
2798+ verify(appDelegate);
2799+ tryCompare(appDelegate, "state", "normal");
2800+
2801+ // now maximize to right
2802+ appDelegate.requestMaximizeRight();
2803+ tryCompare(appDelegate, "state", "maximizedRight");
2804+
2805+ // switch to fullscreen
2806+ app.surfaceList.get(0).requestState(Mir.FullscreenState);
2807+ tryCompare(appDelegate, "state", "fullscreen");
2808+
2809+ // restore, should go back to maximizedRight, not restored
2810+ appDelegate.requestRestore();
2811+ tryCompare(appDelegate, "state", "maximizedRight");
2812+ }
2813+
2814+ function test_altTabToMinimizedApp() {
2815+ loadShell("desktop");
2816+ shell.usageScenario = "desktop";
2817+ waitForRendering(shell);
2818+ swipeAwayGreeter();
2819+
2820+ var appSurfaceId = topLevelSurfaceList.nextId;
2821+ var app = ApplicationManager.startApplication("dialer-app")
2822+ waitUntilAppWindowIsFullyLoaded(appSurfaceId);
2823+
2824+ // start dialer
2825+ var appContainer = findChild(shell, "appContainer");
2826+ var appDelegate = findChild(appContainer, "appDelegate_" + appSurfaceId);
2827+ verify(appDelegate);
2828+ tryCompare(appDelegate, "state", "normal");
2829+
2830+ // minimize dialer
2831+ appDelegate.requestMinimize();
2832+ tryCompare(appDelegate, "state", "minimized");
2833+
2834+ // try to bring dialer back from minimized by doing alt-tab
2835+ keyClick(Qt.Key_Tab, Qt.AltModifier);
2836+ tryCompare(appDelegate, "visible", true);
2837+ tryCompare(appDelegate, "focus", true);
2838+ tryCompare(topLevelSurfaceList.focusedWindow, "surface", appDelegate.surface);
2839+ tryCompare(topLevelSurfaceList.applicationAt(0), "appId", "dialer-app");
2840+ }
2782 }
2841 }
2783}
2842}